Except that OCaml is still (for the foreseeable future) single-core only, just like Python, yet it doesn't have the ecosystem Python has. How many good database drivers are there for OCaml? How good are the web frameworks? If I wanted to write a Kafka consumer in OCaml, which battle-tested library would I pick? If I wanted to send an email through {MailGun, SendGrid, Postmarkapp}, are there any integrations that help with that?
Even an example of an echo server doesn't look that appealing: https://dev.realworldocaml.org/concurrent-programming.html#i... But, perhaps that is just unfamiliarity on my part. Rust was heavily influenced by some of OCaml's choices, but they chose to make the syntax more familiar and approachable to people coming from the mainstream programming world, although it does have its own quirks.
With Go and Rust as options, I'm not sure why someone would pick OCaml in 2019. In 2014, when that article was written, Go and Rust were both much less mature. I hear ReasonML/OCaml could be interesting for frontend work, but frontend is not my specialty.
Honestly, as easy as it is to hate on the npm ecosystem, Node.js can run circles around Python in performance, and TypeScript offers a pretty nice type system. If someone just wants a "better Python" for web-related stuff, TypeScript on the backend might be a good option, although I personally lean towards Rust and Go, depending on the project.
> I'm not sure why someone would pick OCaml in 2019
You definitely would if you already have millions of LoC in OCaml.. like Jane Street does.
For a random person, I would agree. I tried it myself for a few personal projects (I know Rust/Python/C++/Haskell reasonably well) and couldn't get myself to like it, subjectively.
Being 'single-core only' is not that much of a problem if you're coming from Python and immediately seeing a huge performance boost compiling to Go-style static native binaries, I think? People immediately jump on the 'single-core' thing with OCaml, but can you explain what exactly it is that you're trying to do with multicore that's not covered by a concurrency library like Lwt or a multi-processing library like Async Parallel?
Or maybe you can just take advantage of BuckleScript's high-fidelity approach to transpiling OCaml to JavaScript, and write some bindings to take advantage of basically everything in the npm ecosystem?
Sure, not every OCaml library is battle-tested, but I think that's not a good reason to immediately discount it. I didn't tell StavrosK to immediately commit to and rewrite everything in OCaml, I said he might find it interesting. Even with Go, Rust, and TypeScript as options, because:
- Not everyone is satisfied with Go's type system or its model of error handling, or its low ceiling for abstraction.
- Not everyone is satisfied with Rust's overall newness and potential compiler and library bugs, its lack of GC and the subsequent having to deal with borrow checking, or its slow compile times.
- Not everyone is satisfied with trying to model the dynamic complexity of JavaScript in a new, explicitly unsound type system. And it's no secret that the BuckleScript compiler can run rings around tsc for compile speed (not even mentioning the more powerful and battle-tested OCaml language).
Multicore is important because it allows as close to perfect resource utilization as you can get on each machine. When you spin up separate processes, you end up with separate connection pools to every other service (such as databases, mail providers, etc.) which is measurably wasteful, but more importantly, you never efficiently utilize your CPU. I've personally witnessed this with Ruby deployments. You can spin up a server per core, but then you always leave some small percent on the table. So then you could spin up more than one per core, but then you're introducing additional resource contention and scheduler overhead, not to mention even more connection pools. Each process also has its own separate garbage collector, which is less efficient than just having a single GC.
These are only a few things, and only discussing IO bound tasks. Once you start doing CPU intensive stuff, the problems are just made worse, especially if you want to spin off background jobs to work on things after finishing a request.
I know that a library of some kind has been written for each thing that I mentioned, but that doesn't make them ergonomic or reliable. The last time that I researched this, everyone discussing their experiences trying to use Postgres from OCaml had nothing good to say.
The TechEmpower benchmarks don't even include a single entry with OCaml, simply because no one has submitted one, which speaks volumes about the size and maturity of the state of writing a web server in OCaml.
For business critical functions like your database driver and your web server libraries, being battle tested is very important.
The Rust compiler is plenty mature, it's built on LLVM, and has had years of real world use by a growing number of companies. The Rust community places more emphasis on stability than any other I've been part of.
But, the async story and web server stories are not currently mature, which is why I'm happy to use Go for those things. Actix is as close to mature as those things get in Rust right now, and it's not up to my standards yet.
For someone to be so upset with all three of those languages on those counts that they decide to shoulder the burdens OCaml brings... that would be surprising. I had already pointed out that OCaml on the web has become a niche thanks to ReasonML (where BuckleScript is the compiler), especially since the web is predominantly single core.
"Explicitly unsound" is pretty funny to me. TypeScript has a really strong type system. To say otherwise as a negative thing at this point is to be purely pedantic in the most academic of ways, in my opinion.
I get why multicore in general is important and so do the OCaml folks, because they are currently engaged in a serious effort to land multicore in OCaml. That said, OCaml currently offers a great concurrency story (Lwt), and multiprocessing solutions that get you to like 90% of the way there when you really actually need multicore. You called me out for being pedantic about unsoundness which can lead to actual runtime errors, but aren't you being pedantic about insisting that OCaml is worthless if it can't squeeze out every single bit of processing power from your cores?
Discounting every OCaml library as not being 'ergonomic or reliable', really smacks of goalpost-moving. Every OCaml library needs to be immaculately designed and battle-tested? It's not even worth looking at otherwise? This is a weirdly high bar. No one even thinks like this about TypeScript, which by the way has library typings that are full of next-to-useless `any` and `function` types.
Agreed, the TechEmpower benchmarks don't include an OCaml entry, but (a) they're only relevant if you care about writing HTTP servers in OCaml; (b) they're only relevant if you care about benchmarks for HTTP servers in OCaml; and (c) the lack of a benchmark in itself doesn't prove anything about writing HTTP servers in OCaml.
The Rust compiler is an amazing effort, but it would be a mistake to equate its maturity level to the OCaml compiler, which has been an ongoing effort for more than two decades now. Frankly I find it strange that someone who immediately attack and dismiss OCaml when it's even suggested as worth checking out–and then accuse someone of being 'upset' with their suggested languages for writing a response.
> You called me out for being pedantic about unsoundness which can lead to actual runtime errors
"actual runtime errors" can and do happen even in Haskell and Ada. Unit and integration tests are important, no matter the language. TypeScript's type system is a huge step up from Python's, and it's better than Go's in many ways. TypeScript's biggest weakness for me is probably that it runs on Node.js, which is single-core.
As I have previously expressed, the major benefit to TypeScript is that it performs much better than Python while offering a strong type system and a strong ecosystem. The main things OCaml seems to offer are a stronger type system and better performance, when compared to Python. OCaml's type system might be marginally better than TypeScript's, but the Pareto principle might suggest that the extra 20% isn't worth the 80% more effort it will require to make up for OCaml's ecosystem. As I've also pointed out that I strongly prefer multi-core systems, you'll notice that I stated up front that I lean towards Rust and Go, not TypeScript. I just think TypeScript is a great fit for the OP, who seems to have been looking for a faster, safer Python (since they're so interested in Rust) with a drop in library for every task (so they can have it done in an hour). The most you have disagreed there is by saying that TypeScript's type system is slightly unsound. Okay. So, you can choose libraries which have really sound types so you can't easily misuse the library, but likely the libraries contain incorrect behaviors. Alternatively, you can choose libraries that are battle-tested by tons of major companies, but their types might not prevent you from every last possible misuse of the library. Either way, you need to write tests for your code to make sure the results are correct. In fact, you might need to write a lot of otherwise common libraries because OCaml is so niche. I don't see how OCaml wins there for the OP's use case, but I'm sure someone finds that trade off preferable.
> Discounting every OCaml library as not being 'ergonomic or reliable', really smacks of goalpost-moving
It's really not, because I made it clear up-front that I was asking about good and/or battle-tested libraries, not just a list of first hits on google. But it is easy to fall back on the defensive by making it sound like I was shifting things around. I literally asked "how good" are the web frameworks, "how many good" database drivers are there, questions which elicit discussion, not just links. Not "are there web frameworks" and "are there database drivers". I tried to be very clear about this up front.
> No one even thinks like this about TypeScript, which by the way has library typings that are full of next-to-useless `any` and `function` types.
I don't agree with your assessment here, since that really just seems like a strawman argument. `any` is a useful tool when used correctly; how else would you build a custom container like a Vec or a HashMap? It would be annoying to have a container that should be fully generic that can only hold some restricted set of types because the type system isn't powerful enough to allow it. However, it would be truly pointless for someone to build a nice TypeScript library using mainly functions that receive and return `any`, so it doesn't follow logically that experienced people would do that. Why wouldn't they just use JavaScript? This idea doesn't pass the smell test. Do you have any evidence for it? In point of fact, people write TypeScript definitions even for JavaScript libraries! This allows people to provide a nice interface into the JS code, so they don't have to see `any` everywhere they look. Why would they care more about the types in JS libraries, which are only approximate, if they're leaving all of their own code without type checking? TypeScript definitions for JS are only approximate, of course, but that's the real world. They're still helpful, just like documentation for a REST endpoint. When you make a REST call to an API, you aren't guaranteed that everything will work as documented, it might reject valid inputs, it might accept erroneous inputs, it might return values of the wrong types... TypeScript definitions for plain JavaScript libraries give you an opportunity to create a wall around your TypeScript code where the unsafety is easier to contain, but there will always be some level of unsafety in the real world. Eliminating 80% of it is a great start. The last 20% is not as easy as the first 20%, and the cost should be weighed against the benefit.
> and then accuse someone of being 'upset' with their suggested languages
I don't think you understood what I had written. I was saying that it's very unlikely that someone would look at all three of Go, Rust, and TypeScript and decide that the specific problems you mentioned are such dealbreakers that they would choose OCaml. I wasn't talking about you or me being upset, I was talking about any third party analyzing the trade-offs, but you seem to have taken it as some kind of attack against you? It definitely wasn't.
I don't hate OCaml. I have followed it for years, hoping it will progress in ways that I find important. Even years ago, multicore was right around the corner: https://news.ycombinator.com/item?id=9582980 but it's still not here, and it's still not in the foreseeable future.
> The Rust compiler is an amazing effort, but it would be a mistake to equate its maturity level to the OCaml compiler
Does it matter that OCaml's compiler has been under development for "more than two decades" if the amount of development is less than has happened on the Rust compiler in half the time? Rust, Go, and TypeScript have had staggering amounts of money and developer-hours dumped into both their compilers and ecosystems over the past few years, while OCaml's have barely moved at all, as far as I've been able to tell.
The uptick on OCaml seems to correspond to Facebook becoming interested, but on every metric (including total number of contributors, total number of commits, total additions, whatever), the Rust compiler has had a lot more developer-hours of attention than the OCaml compiler, which could be argued makes it more mature than the OCaml compiler... and this is just the Rust compiler frontend itself, which doesn't include the unbelievable amount of time and money that has been sunk into LLVM by Apple and others, which directly benefits Rust.
Let's just say that I don't agree with your conclusion about their relative maturity.
Let me reiterate: I do not hate OCaml. If anything, I'm annoyed with its stagnancy. It has so much potential, and I wish that potential would be realized. ReasonML is the best thing to happen to OCaml in the past 10 years, but that project has been so tightly focused on its objectives that it hasn't bolstered much of the surrounding ecosystem that would be desired for server-side initiatives.
I don't see how this comment thread can become productive, so I'm probably going to bow out now.
Yes, it is quite a lot faster (as well as being older and just generally more featureful after decades of refinements. For example, or-patterns in pattern matches).
It I understand correctly, Rust just got a limited form of or-patterns, with the requirement that they must be isomorphic (introduce the same number of bindings of the same type).