Elixir and Clojure are two uprising and fun functional languages. As you know, I talked about both of them in the article on the most promising languages of 2016, and, in fact, they are the only real functional languages I mentioned in there.
At the time, I didn’t really explore these two languages in deep, and in fact, I think I was a bit too hard on Clojure. During this half year, I had the opportunity to go deeper in Clojure and my opinion on the languages increased accordingly. Moreover, Clojure 1.8 came out just a month later with some nice improvements and the upcoming Clojure 1.9 (with the introduction of the `clojure.spec`) seems to push the bar even further. So, yeah, I was wrong on a big point: Clojure is advancing quite fast.
However, even if Clojure is a more established language, I preferred Elixir in the list as the most promising language. Well, after everything I said and after this half year of experience, I have to say that **I will still put Elixir on top of Clojure again. **And now, I will explain why.
What they share
Elixir and Clojure share a lot. They are both non-pure functional languages running on a Virtual Machine. They are both built on the shoulder of a giant collection of libraries (for Clojure is Java, for Elixir is Erlang). They are both focused on high concurrency. They are both dynamically typed. They are both quite young. They are tackling the same use cases.
As you see, they are very similar in many ways and it is natural to put one against the other. In some sense, they are rival.
If they are so similar, why do you prefer Elixir? Before that, I need to clarify something: I don’t have any real-world big project with both languages. Therefore, take this with a grain of salt.
There are some aspects that I really love of Clojure. First, I like that Clojure is a modern lisp implementation. While Elixir syntax is heavily Ruby-inspired (a big pro if you came from Ruby), Clojure has the timeless elegance of Lisp. This is very subjective, I know. Also because it’s hard to say that, for instance , Clojure’s list comprehension is nicer than Elixir’s one.
But, you know. Lisp has some strange kind of beauty for me.
The second upside of Clojure is the Java Virtual Machine. Both JVM and BEAM (the Erlang Virtual Machine) are magnificent pieces of software. But the JVM is slightly faster and it definitely has a larger diffusion (that means, more people are testing the JVM and so it is more optimized/bug-free, in theory). This also means that Clojure can, again, in theory, work on Android (almost) natively. Moreover, you can use every _enterprise approved _tools of the JVM. Another big score.
Clojure has also a bigger community at the moment. That is always a good upside.
But other that these points, I don’t really know why I should prefer Clojure over Elixir.
Elixir’s Upsides (Clojure’s Downsides)
There are many points for which I like to play with Elixir more than Clojure. I will focus on three of them.
First, the tools. I find Leinigen a bit bloated respect to Mix. Mix is faster, lighter and integrated with Elixir. Lein is not. I find Lein a bit slow, because is in Clojure and Clojure it is not a really good choice for command line tools.
This brings on the table the second point: startup time. Clojure is completely unpractical for quick command line scripts. This is not a big deal for webservers and other “always run” applications. However, I write mostly command line tools and this Clojure problem completely force me to avoid Clojure in my daily job. It is a shame.
Finally, the third and most important point: the error messages and the Java layer. The confusing error messages in Clojure are a common complaint. The main problem is that these errors are, mostly, Java errors. In other words, you speak Clojure and the compiler (or the runtime) speak Java.
java.lang.ClassCastException: clojure.lang.PersistentVector cannot be cast to java.lang.Number
This is an example. The Clojure error starts with
java.lang. This error is referred to a wrong type passed to a function, but the error is in Java and talks about
PersistenVector. Other errors are even more confusing. Plus: the stack trace is the Java stack trace. And it is not easy to map that to Clojure’s calls.
In my opinion, in Clojure, the Java layer pokes the Clojure layer way more than it should. Another example is that Clojure require to access the Java standard library in many cases. The problem with this is that Java functions and Clojure functions are not interchangable. For instance you can do
But you can not do
You need to wrap the Java function into a Clojure function explicitly in this way
I don’t find this particularly elegant.
Because Elixir shares most of the strong point of Clojure and none of the weak point, I think that in the long run Elixir is a better bet. Obviously, this can change depending on how the two communities will develop their language. However, right now, I’m really enjoying Elixir and I almost dropped Clojure. It was a pleasant discovery.
I cannot wait to see if in the future Clojure will steal the Elixir place in my personal ranking! :)