EDIT: This post has been translated to Japanese.
Every once in a while, someone, somewhere, decides it’s time to write yet another post on what’s the best programming language, the mighty properties of a forgotten language, or the new language that does it right. So my time has come. Finally, I get to say what I think about programming languages.
First of all, a disclaimer: unless you’ve developed in 30+ languages, and suffered the code of others in all (or most) of them, you can’t really be objective. So yes, I’m biased. Like most of the people writing about this topic. Actually, I believe that this topic becomes absurd as soon as you are well-versed in many languages.
TL;DR: The Great Languages
I hereby declare these languages to be The Great Languages within the realms of my blog.
- Assembly: the language of the machine.
- C: the systems language.
Most of the code examples are from Rosetta Code.
The Reasonable languages
I don’t call these reasonable languages because I think they are the best languages. They just are the languages people use most nowadays, which makes them eligible for production software. Of course, you can bypass this argument and just go for gut decisions. In that case, go to the next section.
I’ve always been curious about the idea of designing a language around memory safety. That makes sense for applications in real-time operating systems and critical systems in general. Probably if you are considering using this language you don’t need to read this, and you come from a highly specialized background. This is one of the languages that you use once you know what you are doing, and then you don’t have many options either. Some bits of Ada:
It looks safe, right? ;)
Bourne (Again) Shell
When would I use Unix Shell?
- OSX/Linux/POSIX system administration
- For task automatization
- To unlock command-line superpowers
Some Bourne Shell code. Enjoy those boolean expressions!
Well, you have to respect C, even if you don’t like it. It’s arguably one of The Great Languages. The language that programs machine reality (not models of). It’s the father of UNIX, all the languages of the capital C, and the lingua franca of systems development. It’s been battle-tested, time-tested and hype-tested. The plethora of tools available for developing, debugging, profiling and supporting C development make it for all its defects as a language (not so many, in my opinion). It’s a language that really achieved its purpose: become a general-purpose Assembly language for every processor. Nowadays, it is the de-facto Assembly for even the strangest architecture, and it has become very hard to make better hand-crafted code than that generated by C compilers.
It is thus a powerful tool, but one that needs to be mastered. The language shows no mercy, and you always need to know what you are doing. That is what makes C the language for understanding the machine. There is beauty in this, and there is a practical side too: there are things that just can’t be done without the kind of low-level that C provides. C programmers must understand very well what they are doing, leading to very solid software in the long run. If there is something that could debunk C is a low-level language with great support for concurrency. Or maybe a mythical language with the properties of Haskell and the pervasiveness of C.
Some C from the Linux Kernel:
A monster. It was my first language, and I didn’t really understand how it was screwing my productivity and limiting my skills until I tried many others. The bad reputation of C++ is promoted by some well-known programmers, and I agree completely. C++ seems as if Bjarne Stoustrup took every single feature he could think of and added it to C. The cognitive load it imposes might make you more than 80% less productive. Think of it this way: you have a brain of X capacity, and that capacity is limited, doesn’t matter how much capacity you have, and you want to leave as much as possible of it for the important things. The wise thing to do would be to reduce the amount of brain power used for the language per se, and use the most of that brain for solving the problem and encoding an algorithm. If the language is complex, no matter how smart you are, you’ll need to use more of your brain for the syntax and the semantics of the language and less to efficiently projecting your ideas onto code.
I think C++ is the quintessential example of too much complexity for not that much gain. I agree, building large programs in C is difficult (but arguably an option, look at the Linux Kernel). Go, Rust and D are better languages by all measures, except for the fact that C++ is what the world actually uses.
This is a nice example of good C++ using templates. C++ works looks much more comprehensible in user code like this, rather than template/classes definitions.
And then some template code, a very simple example (which tends to grow naturally in an awful way).
Enterprise language that aims at reducing any kind of programmer creativity that might hinder its replaceability in any large organization. Object-oriented, statically typed, verbose, with heavy libraries and lots of boilerplate. You can see Microsoft’s hand behind this creation. But don’t get me wrong, is not a bad language. It just isn’t sexy, which precisely is what Microsoft wanted in first place. At least, is a radical improvement when compared with Visual Basic. I would use it for:
- Windows development.
- Game development (well, mostly because Microsoft forces developers, but I would still prefer good ol’ C/C++).
- There are huge things going on in this language: Unity3D, Xamarin, .NET, XNA.
Here’s some code.
Wouldn’t you say it resembles Java?
I have a much better opinion of Objective-C than of C++ (and C#). It’s syntactically ugly, but I like it as a language. It’s got a great set of libraries based on NextStep, with the plus of being a real improvement upon C, without growing too much out of control and bringing ambiguities in keywords with its parent language. As I said, it’s a bit ugly and difficult to read, especially when nesting functions, but definitely its beauty resides in its conceptual approach, not in its syntax. See this nested calls:
This is beautiful code for a son of C language, making use of Objective-C’s so-called blocks.
Being a Scheme programmer I have respect for Clojure: it’s a so-called modern Lisp, with some unique features. I’d say Clojure’s strong points are Java interoperability and concurrency utilities in the core language. It’s a sibling of Scala, but differs in their flavor: lisp vs. hybrid OOP/functional, making Clojure less popular due to the excess of parenthesis. Choosing one of these two for a project it’s a matter of tastes, because neither are proven technologies with a long track record of successful production applications, as compared with Java or PHP, although they both stand on the shoulders of JVM. Another thing to take into consideration for any JVM-base language is the startup time of the virtual machine: it doesn’t seem like a very lightweight solution for small tasks. These are the situations where I would use Clojure:
- Web development. There are good options for this, and the Clojure community seems very active in this area.
- When you want to use the JVM technology without the Java thing. Both programmer happiness and productivity will improve.
- Exploratory programming, that could grow into production code. This is actually an area where its Lisp nature really shines, but Clojure relies on the Java stack, exposing many production code to it.
- Android development? Android development GUI development model relies heavily on class inheritance (meaning that you don’t actually use it as a plug-in library, it forces you to follow a certain structure). It can be done, but it certainly isn’t as natural as direct Java inheritance.
Some classical Clojure code:
And a simple queue definition in the lisp way.
I used to love D. D is like C++ done right. D1 felt like a low-level-oriented Python. Like a pythonized C or something like that. It’s awesome: you feel development speed, focusing on the algorithms and not the language, but you don’t sacrifice low-level control when you need it. D2 brought a lot more of the complexity of C++, with the innovative touch of Andrei Alexandrescu. That made part of the community unhappy, albeit D2’s focus on concurrency. D2 is not a clean language any more, but feels more like an experimental language with lots of untested features. I like it though, but I think it’s features pale in comparison with C++’s pervasiveness (once you have a more complex language). And also I think Go took the place that was once D’s destiny. Walter and Andrei can’t compete with Google, even if they can move faster and implement really cool things in the language. You can like D (as I sort of do), but I don’t see a bright future for it. Just stick with C++ or go to Go for better native concurrency support. So, when would I use D?
- For developing a project from scratch, being able to interface C and to some extent, C++. You have to think in advance what those interfaces are going to be like, though. For instance, I wouldn’t recommend it you need to use a C++ GUI library, because that normally means dealing with C++ inheritance from within and that will throw all the advantages away. Just do this if you need C++ for a plug-in library (creating objects and using its functions, but no templating or C++ inheritance).
- If you need low-level programming with fast binaries. Again, doing your own thing, like a standalone program.
- If you want better native support for concurrency in the language.
Let’s see some idiomatic D2, with pure functions, and immutable declarations.
The max element of a list.
It is definitely more expressive and a cleaner language than C++, by far.
This is a very specific-purpose language. Erlang’s web page describes it very clearly: […] build massively scalable soft real-time systems with requirements on high availability. Some of its uses are in telecoms, banking, e-commerce, computer telephony and instant messaging. Erlang’s runtime system has built-in support for concurrency, distribution and fault tolerance. Erlang has been proven for, and its behind some very demanding applications such as WhatsApp. The code itself feels very functional, and its syntax is clean and very readable.
Take a look at the code for a simple concurrent program:
I haven’t used this personally. Yet. But it’s clear that this is Google’s take on making a C with the good parts of C++ and better than both in its concurrency support. It has better features than C++, and it is way simpler. It has no unsafe pointer arithmetic, closures and first-class functions, and garbage collection. Go might become the server language in the future. So, when would I try Go?
- For server applications that need very high reliability and performance. This includes web apps.
- For highly-concurrent code that requires low-level control (otherwise, I’d stick to Erlang).
Go concurrent code:
This language truly feels as a more advanced thinking tool than the others in this list. It has libraries for almost any need and it has a hard-core community. Arguably it’s a language with a high barrier of entry. It will expand your mind, and surround you with some of the brightest minds in the programming languages communities, in my opinion.
I think Haskell is well worth learning, even if you don’t build any real program with it. Being a relatively obscure language, I chose to classify it as reasonable since it is actually used in several areas, and especially in the financial industry. Haskell’s code tends to be very compact and expressive, albeit a bit abstract, in the sense that you need lots of functions that are actually conceptual operations rather than steps of a process. I personally don’t like its syntax (I think it has way too much syntax), but at least it serves a purpose and doesn’t feel like clutter (I’m looking at you Perl!). This language feels beautiful and coherent. Take a look by yourself:
The same as C#, but for the Java Virtual Machine. Was there first (in fact C# copied it), and it’s sort of “the standard” object-oriented language in the industry. It’s used for everything, from web apps to games. Almost everything except embedded device software, and perhaps high performance parallel computation software. It serves as the foundation for many other languages (specifically its virtual machine). Take a look at Processing for an interesting project, where a wrapper language (just sugar-coated Java) is used for education and digital art. When would I personally recommend you Java?
- Mostly when you want to access a very large pool of developers and knowledge base, i.e. You want the software to be maintained by someone else.
- When you need a multiplatform virtual machine present in as many devices as possible.
Java 7 code example, reading a file:
I guess you’ve seen more Java code before, so I’m not going to bother you with a class definition.
And this shows functional-style code using the Lo-dash library:
It’s sort of like Haskell, but it feels like more willing to bend to the programmer’s desires. When there is need, some compromises to its purity are made in benefit of easier solutions, for instance when the procedural/object-oriented approach seems to work best. There are companies using it, I guess just for this benefit over Haskell. Take a look at this little snippet:
Looks almost like Haskell, right? But then you have the imperative flavor in that for loop…
Don’t just assume PHP is horrible. Be a good spartan and inflict yourself the joy of PHP. The good thing is: if you enjoy programming in PHP, then you are a true programmer. And it’s the language of the cheap freelance work. When would I use PHP?
- If you want to have the largest pool of web developers available.
- That’s it, no other reason.
Pretty code in PHP. I hope you like dollars.
- Web development.
- Scientific computing and data analysis.
- System administration and tools.
- Game/3d application scripting.
- Cross-platform support.
Nice Python code:
Ruby on Rails. The single reason this language could ever be part of this list. Of course, nowadays it’s easy to see it in many other projects, but it all began with Rails. Before that, Ruby was an obscure programming language from Japan. This is a perfect example of how a killer app/framework spawned a great community which in turn made more killer apps/frameworks and made the language popular even though the place for this sort of language was supposedly taken.
One thing I’ve heard from many Ruby developers and I had experienced myself, is the actual joy that comes from using it. In other words, it’s the contrary of a frustrating language, although I don’t know if this is something from the language or Rails itself. The guys at metasploit seemed to have it very clear since the beginning as well.
Here’s the same algorithm shown in Python, this time in Ruby. It follows a different approach, which shows also the tendency of Ruby to use a slightly more functional style.
Seems to be winning the race for the best JVM-based language award. I’m pretty sure that most of it comes from a familiar syntax, when compared with Clojure, the other big contender. As in Clojure, the reason this language is in this list is because its easy interfacing with Java make it a viable choice for a real project. Look at this small snippet generating the Hofstadter Q sequence:
This is probably a controversial language to be on this list, but I have an explanation. The three main issues associated with this language are:
- Lack of one true implementation and multiple competing ones of dubious quality.
- Lack of libraries.
- Poor performance.
Well, the first one is partially true (there are too many implementations), but there are only a handful of good ones and you need to choose the one that best fits you. The second is also partially true: there are libraries, but they are scattered. There are some projects that offer alternatives, and lots of tiny projects out there. The fragmentation of the language is made obvious when looking for support code: you need to make it work with your implementation. However, this is often not so difficult or time-consuming, and most importantly, if you use Scheme implementations with good FFI support, such as Gambit or Chicken Scheme, you have easy access to all those libraries in C. I actually do it, and works great, contrary to what you may think. Finally, poor performance. This one is actually completely false. Implementations such as Gambit are very fast, and you have plenty of options for optimization (starting from algorithmic optimization, global Scheme compiler declarations, and of course, C code that can be easily interwoven with the Scheme code when necessary).
- For exploratory programming, when I don’t exactly know where I’m heading.
- For fast prototyping of ideas that don’t really require a large library only available in languages like Python or Ruby.
- For scripting large programs or platforms developed in C/C++.
- For building an application with large portions that need to be written from scratch.
- For games and OpenGL/ES-based multiplatform applications.
Here you have three examples of Scheme code. You actually have to implement these functions yourself as they are not directly available across all implementations, even though they are rather useful and common enough. These would work across all implementations (provided they are R5RS-compatible).
Take a look at these other interesting examples too.
If you solve the issue of a minimal development framework (yourself or via projects like Scheme Spheres, then you are on a flywheel.
Not necessarily good or bad. They just seem to be forgotten, there is no more hype about this languages, and there seem to be no compelling reasons to use them. But maybe we are wrong!
Nobody really codes in Assembly any more, not even for optimization, since compilers are much better at this task. Well, there is always someone better than the compiler, but you must be very, very smart and knowledgeable for that I presume.
But there is one very important reason why you must use it: for the ultimate programming experience. There is this enlightening experience that you are blessed with SICP and the Lisps, but I believe there is this other enlightenment that comes with really understanding what all languages end up being: just a sequence of processor instructions, that abstract away from languages their own high-level constructs, no matter if they are declarative, logic, functional or object-oriented. That’s power for your programmer brain. This is a language that belongs in The Great Languages category. When would I use learning?
- For learning.
- For systems development there are some situations where you need to use it.
- When you know a lot about an specific architecture and need a specific portion of code to be hand-crafted.
I’ve used Autolisp, for AutoCAD automatization, but once faced with the Lisp/Scheme/Clojure decision, I choose Scheme. For me, it ranks third among the three reasonable Lisps. It feels bloated and missing the most important features of a lisp: beauty, elegance and simplicity. I would use it for rapid prototyping, it has the advantage over Scheme of the readily available libraries, but we’ll see that Scheme makes up for this disadvantage. And, I think there are better languages for prototyping with libraries.
Great songs have been written in Perl. Apparently is a language of religion, with its monks and its prophet. There is something to the fact that Larry Wall, its creator, is a linguist, something that you can see projected into the language. Feels like the Latin of programming languages, which I find really fascinating. Guys, wise folks in the industry are still talking about Perl, so there must be a reason. The spirit of the language is captured in one of Larry’s witty quotes ‘Real programmers can write assembly code in any language’.
Overall, I can say I am impressed by the linguistic notions in Perl. But its funny syntax could be used for great harm in the wrong hands (much in the way Lisp macros can). I’d say the language is great for solving small tasks in a very handy way: it has a comprehensive set of libraries (CPAN) for almost any task you want to, leading to the simplest solutions that could possibly work. Using Perl the worst that could happen is that you learn a very valuable tool for scripting your system. Ps: I’ve been told Perl’s object support it’s plain terrible, but I count this as a benefit (I might be biased, though), but I also doubt this assertion.
BASIC, COBOL, Fortran, Pascal, Visual Basic…
The gods have mercy with you if you need to program in any of these languages. They may have a very specific usage (like, Fortran in the Astronomy and HPC communities), or COBOL (large legacy systems in industries such as banking), but they all get almost unanimously bashed by the developers community. But I offer you a very good reason to use these languages: you’ll be able to sport a pretty sweet hourly rate for fixing code of others. For your own code? Don’t even thing about it ;)
The first true object-oriented language. But it seems to me Smalltalk is pretty much a forgotten language.
The Unreasonable languages
Unreasonable probably for production purposes, but will definitely make you a better programmer (that being perfectly reasonable). Your is the choice of what counts. And what I can say, I love unreasonable options.
These are languages that I need to learn, as I’ve heard that they are unique and learning them will expand your mind beyond functional and declarative languages.
Stack-based languages are also very powerful and worth learning. Useful for expanding the mind. On my TODO list.
Microsoft trying to be cool. It’s a nice language, but many of us have learned to keep away from Microsoft the hard way. We have enough company-sponsored languages already.
It’s a very multiparadigm language, with constraint and distributed programming functionality. It has most of the features of the major programming language including functional (both lazy and eager), imperative and object-oriented.
Declarative logic languages are generally very academic languages. There are exceptions though, as can be seen in this Stackoverflow question, and the same could be said about Scheme.
Mozilla’s contender to the systems programming language competition. It doesn’t have the history of D behind it, or the support of a huge company as Google, such as Go does. Still, I hope to see Rust as a reasonable choice for systems development in the near future.
This is just here because I read interesting stuff about skinnable type systems, and some other very radical and interesting ideas in Shen. However, its implementations are extremely experimental and the language has an unacceptable license. The creator seems to live in another decade.
I used it for a few months, when the fact that it is homoiconic and it had bindings to a library I needed back then (BRL-CAD) was all that mattered. I’d say is an underrated language, but just as so many others are. It doesn’t shine with any super-cool features either (à la Erlang).
I started this long post with my selection of choice. Programming is a beautiful craft, that I love whole-heartedly, so I admit that I’m heavily biased according to my personal experience. Choosing a programming language for a task or project is sometimes difficult, as so many variables take place. In my opinion, there are three that prevail, in this order:
- Is the project aimed at production, or belongs to a sufficiently large organization with a culture or bias towards a programming language?
- Is the task at hand sufficiently special to require a programming language with very specific features?
- Do you love or want to try developing in that programming language?
That’s how I approach this issue. Even though sometimes I break the rules…