As I’m about to start my PhD studies here in a couple days, I thought it might be interesting to put down my thoughts about what would make a very strong contender for “best” programming language by listing the features this language would have. In a few years time, I can (hopefully) return to this list and see how my opinions have changed.
General-purpose
To start off, I should mention this PL has to be general-purpose because otherwise how could it be “best”? The original title of this post was “Building a Perfect Programming Language” but really languages will always favor expressing some concepts over others. There isn’t one that’s perfect for everything. That said, this language should be able to fill the most needs, and do so with minimal effort.
Bare metal
Some may disagree with me and say that I spent too much time looking at the language shootout. Really, though, this comes down to being truly general-purpose. If you can’t be compiled to the bare metal, you can’t be used in things like embedded devices, operating systems, device drivers, high performance computing, scientific computing (large-scale)… really any performance-bound application. It’s not an accident that both web browsers and web servers still use languages like C/C++.
Zero compile time during development (aka Show me the REPL)
This may seem to contradict the previous point, but languages like Python, PHP, and Ruby have really shown us, it’s important for a sizable sector of programmers to be able to tests out different ideas quickly to shape their mental models of how the app should work. This requirement also stems from the original general-purpose requirement above. If the language doesn’t work for the sector of programmers that need a very tight feedback loop, then it’s not general-purpose.
How can this be accomplished with also being bare metal? Languages like Haskell and Common Lisp use what’s called a REPL or read-eval-print loop. This gives the programmer a way to plug into the brains of the language and try out ideas at what resembles a bash prompt.
Applications must be verifiable
There are two main circles of thought in program verifiability: full coverage unit testing and automatic verification.
Unit testing, pushed heavily by agile programming figures like Bob Martin and groups like the Ruby on Rails. There are a few flavors on this theme, but the end goal is the same: an informal executable spec that can demonstrate that for some cases your application performs correctly.
On the other side of program verifiability is automatic verification, the most popular of these is static typing. Strong type systems, like those found in Haskell, Scala, or OCaml (and to a lesser extent C++ and Java) are built to make requirements of your program expressible as types. Using types in this way makes up a formal, but incomplete, proof of the correctness of your application.
So, between unit tests and automatic verification with static types, which should we choose for our “best” language? I’ll give you the cheeky answer: “How much do you like debugging?” If you’re like me, you hate it, so the more the compiler can catch the better. Others will want the compiler to be more relaxed, especially when prototyping.
What we want is a dial on the compiler, some setting that tells it how much to enforce formal methods on the user to prove that the application works correctly. For “launch the missiles” type applications, the programmer can crank it to the max and require total application verification. For the web application you’re building for your bowling league’s website, perhaps a lower setting would be sufficient.
Implicit parallelism with visual profiling
I’m going to give you a million dollars and put you at a casino table. The bet: “Will computers be more parallel or less parallel in the future”? You’ve got to bet it all in one direction, which do you pick?
If you bet on “less parallel”, you can focus your efforts on meeting the needs of your users with the type of hardware we have now (4 cores or less), using the languages we already have available (namely C/C++), with minimal effort. Good to go.
Let’s say computers, starting tomorrow, had a 1000 cores. Now, plan how you’re going to get the edge on your competitors who will also be scrambling to use this newly found 1000 cores of awesomeness. Who is going to get the edge, and how? You might say “but my application doesn’t need 1000 cores, it runs fine on 1.” That’s fine, but imagine the number of new features your competitors can add leveraging all that new power.
Explicit parallelism, the kind where you’re literally spawning threads, locking locks, and passing messages, has two serious disadvantage: you need to know where and how to make your application parallel. Implicit parallelism, the kind where loops are performed in parallel for you, has its own serious disadvantage: you don’t know where the compiler will make something parallel.
Enter “implicit parallelism with visual profiling” – along with the compiler’s ability to make code parallel, the programmer needs a way to view the code as it runs to make sure the performance is there. A visual profiler gives you the ability to do this kind of probing to find the bottlenecks in your application.
So why did I pick implicit over explicit here? Let’s say that the “sky is falling” alpha geeks are wrong, and that we aren’t entering a massively parallel age. Tomorrow, Intel comes out with a new single-core that runs 10x faster than the current processors. Why should you have to maintain explicitly parallel code when the processors aren’t using it? That’s just extra work and (in all honesty) probably something of a maintenance nightmare. If it’s implicit, you at least have the option of going parallel again in the future without being pressed to maintain it in the interim.
Readable
I highly recommend Barbara Liskov’s OOPSLA talk (a reprise of her Turing award lecture). No, it’s not stuffy, it’s awesome, watch it.
Two points really got drilled home to me watching the talk: 1) Why aren’t there more women in computing, esp. programming languages? We could use them. 2) Programs always, always, always should be readable.
How do we make our “best” language readable? Probably the best way is to try to avoid being unreadable. Features like a giant number of operators, unnecessary concision, operator overloading, and syntactic extensions are all two-edged swords. Yes, for some minority readability actually goes up, but the time investment required to get to that stage is prohibitive for programmers at large.
Conclusion
There we have it, six features for the next best programming language, and there no doubt could be others. The functional programming camps, high performance camps, scripting language camps, and just about everyone else likely have their own two cents for what should be in the list. When it comes down to it, really only one things matters for this next best programming language: it gets the job done.