Over the years, I've had many conversations about programming languages. Looking back on them now, they were mostly pointless. However, I think there are a few areas ripe for improvement.
To date, compilers, editors and code management have all been seen as separate. This places bounds on improvements because parts taken and improved in isolation either aren't effective or have a detrimental effect on the system as a whole.
Almost all programming languages and editors read and write plain text files. This means that what the engineer edits, what the compiler sees and what is stored on disk are forced to be the same at all times. This has the following effects:
- it prohibits real out of band information, eg comments and inline documentation.
- storage can't be optimised for anything other than editing, eg use of a tree structure to aid language agnostic comparison tools.
- style can't be separated from content - where do you like to put your curly brackets? The compiler doesn't care so it should be an editor thing.
Code blocks are currently special in popular languages. This can be evidenced by trying to replicate if within the language using code blocks. For example, in Java, one would have to use multiple classes adhering to an interface or reflection to get the same thing. This is a problem when you're passing code blocks to other parts of the system to be run.
Chopping it all up
The code you write is rarely an island. Your product is not your code; your product is the sum of your code and many other components you didn't write. The management of your code within the context of the multitude of components making up your product is critical. This includes taking account of dependancies across versions and multiple versions of the same component within a system.
Here are two examples of creating a mutable hash table:
Map options = new HashMap();(in Java)
NSMutableDictionary options = [NSMutableDictionary dictionary];(using Cocoa)
Functionally, they're are almost identical. However they are slightly different in that in the the Java example the engineer chooses the performance, and in the Cocoa example, the engineer leaves that up to the underlying API.
Neither is strictly wrong, but neither is quite right either. Java should not force the engineer into premature optimisation, but it's difficult to see how Cocoa can always get it right at run time. There are many examples of this kind of thing in most major languages, especially in the type system.
I suspect that a full versioned bundle that exists both on disk and within the version control system as an atomic object would be a good start. This would contain both source code and compiler output, along with dependancies and version preferences.
As for what the language itself would be like, I think it should at least:
- natively support multi-threading and the throwing around of code blocks.
- not contain anything the compiler can work out for itself. Anything not critical to program flow should be in a side channel.
- not present false dilemmas with regards to optimisation. This could be by allowing the engineer to state a preference in a side channel, or performance metrics from test systems to update the preference for specific platforms.
- put anything the compiler doesn't need but the engineer would like in a side channel (eg comments) or in editor preferences (eg style information).