back
10 comments
I've often wondered why OCaml isn't more popular. There was a time when it utterly dominated the various benchmark games, both in brevity of code and in performance.

Of course, I never used it for anything, so I should probably ask myself why I never used it, knowing how concise it is and how fast it seems to be...

It suffers from a lack of tooling and libraries, mainly. If more people used it, it would create a demand for these gaps to be filled. Anecdotally, the runtime also falls down when you need to use large arrays or strings, or do lots of floating-point calculations.

Even though it doesn’t have all the features of OCaml, I think F# is an eminently practical substitute, considering that the CLR and Mono are both quite solid, battle-tested runtimes, and using F# gives you access to a large body of C# libraries.

Then again, there are a lot of things to like about OCaml. The compiler is fast, the error messages are good, there are some advanced type system features to improve the correctness and performance of your code, and (as with F#) you can freely mix imperative and functional features as you see fit.

> Anecdotally, the runtime also falls down when you need to use large arrays or strings, or do lots of floating-point calculations.

Anecdotally from one specific well-known troll. (I'm not saying it is or isn't true, just that almost all of these claims originate from a single individual with an axe to grind).

I was referring to my own (limited) experience and stuff I’ve read from Jane Street. If people have axes, let them grind them.
> the error messages are good

I'm not sure about that.

There is some work to improve the type error messages, although the existing ones are quite useful already: http://ocaml.org/meetings/ocaml/2014/chargueraud-slides.pdf

And syntax errors are improved if you use merlin, for example for this typo it highlights the ';':

  let foo; x = 4

  Syntax error inside `let', expecting ':' or '=' function body
the language has always been beautiful and a pleasure to use, but the surrounding aspects like a good stdlib, build system and package manager were pretty bad, and have only been improving in the last few years. and now that things have improved in that direction, the lack of good multicore support weighs against it. it's still a great language though, and as a casual user i'm pretty optimistic about its future.
Another problem is the lack of marketing.
I'll give what I consider to be reasons why the language isn't more popular, but it seems most people that use the language don't share these views. Please don't flame me for the excessive rant below and keep in mind these are subjective reasons (that may be badly worded, (it is 2am) or even worse simply misinformed).

- The compiler error messages are awful, especially for newer programmers. By awful I really do mean awful. "Syntax error" is not a very meaningful message, but at least it tells you the location right? Except due to the poor grammar of the language (I did say these objections are subjective) a small mistake like a missing in or semi-colon results in a wild chase trying to figure why you are getting a "syntax error" in a perfectly valid piece of code.

- Unpolished language grammar. There are just a lot of small things that bug me about the language like the existence of "in" for let statements (Rust's approach feels much cleaner), having multiple ways to create blocks (begin..end, and parenthesis), having to type rec for recursive functions, difference between declaration of functions in mli and ml, argument sigs and function sigs use the same delimeter, let is used for binding functions, imperative mode using refs is just plain ugly. These are minor and almost entirely subjective objections, but the real issue isn't just a lack of polish, it's that the language is too unrestricted.

- Language is too unrestricted. 1) It's often very difficult to read other people's code because there are many ways to accomplish the same thing. 2) The language almost invites you to have high levels of nested logic (something considered a cardinal sin in imperative programming) to the extent that it's not uncommon to see (or be tempted to write) 6 or even more levels of depth. 3) Easy abuse of lambda functions (fun and function) can make it difficult to even know how many parameters a function really expects. I mean this in the sense that you need to carefully read the code to get an idea of even whether a let binding is a data binding or a function binding. Of course these are all things you learn to handle and manage with some experience, but they really don't make the language an easy pick-up.

- Language is difficult to reason about internally. Let me give an example. OCaml can be very clever sometimes, like when you prepend to a list, that's an O(1) prepend with no copy of the initial list even though it's immutable. To write better OCaml code you need to become familiar with such things (though I suppose that's true of any language) and sometimes it's not easy (for me at least) to guess internal behavior. For example, does "let t = {t with x} in" modify t in place even though t is immutable (assuming we are the same level where t is first declared, i.e. initial t is no longer reachable) or does it create a new copy of t and then modify the x in that new copy? I guess a fair counter is, who cares?, and I get that, but at the same time I have some underlying drive that makes me want to know (the answer is the second one, the data is copied) at least things such as when I am allocating new memory.

The last big one and the most controversial of all - (purely) functional programming is not worth the trouble. It is inherently more complicated than imperative regardless of all the functional people claiming otherwise. It's not as simple as "you learned one first and that's why it's easier", an argument I've heard repeated many times, one that probably has merit, but also one that cannot account for the difference in difficulty. I can write an entire paper on why functional is more difficult (essentially it will use most of the reasoning as Out of the Tar Pit - which argues that functional is great - but with some changes in the argument to result in an opposing conclusion). In terms of informal reasoning, the benefits of lack of internal (to a function) mutable state are essentially zero, or better worded, lack of local mutable state increases the complexity of a function. It's not like your state doesn't change if you use recursion and immutability... it certainly does, it just mutates transiently while you are building up your result. That's often more difficult to reason about than a typical imperative solution with mutability. Okay, fine, perhaps I am a shit developer who simple isn't smart enough or lacks the experience, but the reality is when you are working on a team, the chances are that you will have a very difficult time gathering 20, 30, or more solid functional developers let alone that many OCaml developers. Ideally, you want your team to all be at least competent in the language you are using and that's harder to achieve with OCaml.

I think OCaml is a lovely language that brings a lot to the table, but I simply can't see it becoming mainstream (or really any other functional language either). The thing that makes sense to me is to merge imperative and functional into some sort of hybrid language, which is one of the main reasons Rust is so exciting. Reduce global mutable state to as low as reasonable while making allowances for local mutable state. Also Rust fixes the three sections of complaints above - great errors and warnings, feels more polished when writing, and forces a much higher rigidity - though it introduces some other issues.

At this point I am not even sure what I'm talking about so I'll end it here hoping the above made any sense at all.

> In terms of informal reasoning, the benefits of lack of internal (to a function) mutable state are essentially zero, or better worded, lack of local mutable state increases the complexity of a function. It's not like your state doesn't change if you use recursion and immutability... it certainly does, it just mutates transiently while you are building up your result. That's often more difficult to reason about than a typical imperative solution with mutability.

But you can have local mutable state in OCaml using refs... In fact, that's exactly how the gen library works (hide a ref in a closure). That said, I find it easier to understand a sequence of maps/folds/filters than figuring out what a for loop is supposed to represent.

> Okay, fine, perhaps I am a shit developer who simple isn't smart enough or lacks the experience, but the reality is when you are working on a team, the chances are that you will have a very difficult time gathering 20, 30, or more solid functional developers let alone that many OCaml developers. Ideally, you want your team to all be at least competent in the language you are using and that's harder to achieve with OCaml.

That's a fair point. On the other hand, it's very difficult to find good imperative programmers anyway, and I find that it's more difficult to shoot yourself in the foot with OCaml.