(no title)
timhh | 3 months ago
I've used OCaml a bit and found various issues with it:
* Terrible Windows support. With OCaml 5 it's upgraded to "pretty bad".
* The syntax is hard to parse for humans. Often it turns into a word soup, without any helpful punctuation to tell you what things are. It's like reading a book with no paragraphs, capitalisation or punctuation.
* The syntax isn't recoverable. Sometimes you can add a single character and the error message is essentially "syntax error in these 1000 lines".
* Ocamlfmt is pretty bad. It thinks it is writing prose. It will even put complex `match`es on one line if they fit. Really hurts readability.
* The documentation is super terse. Very few examples.
* OPAM. In theory... I feel like it should be great. But in practice I find it to be incomprehensible, full of surprising behaviours, and also surprisingly buggy. I still can't believe the bug where it can't find `curl` if you're in more than 32 Unix groups.
* Optional type annotation for function signatures throws away a significant benefit of static typing - documentation/understanding and nice error messages.
* Tiny ecosystem. Rust gets flak for its small standard library, but OCaml doesn't even have a built in function to copy files.
* Like all FP languages it has a weird obsession with singly linked lists, which are actually a pretty awful data structure.
It's not all bad though, and I'd definitely take it over C and Python. Definitely wouldn't pick it over Rust though, unless I was really worried about compile times.
delta_p_delta_x|3 months ago
I couldn't agree more with the parent commenter about OCaml documentation. Functional programmers appear to love terseness to an almost extreme degree. Things like `first` are abbreviated to `fst`, which is just odd. Especially now that good IntelliSense means there is no real functional (heh) difference between typing `.fi` and pressing Tab, and typing `.fs` and pressing Tab.
The F# documentation is comparatively very spiffy and detailed, with plenty of examples[1][2][3].
[1]: https://learn.microsoft.com/en-gb/dotnet/fsharp/language-ref...
[2]: https://fsharp.github.io/fsharp-core-docs/
[3]: https://fsprojects.github.io/fsharp-cheatsheet/fsharp-cheats...
Syzygies|3 months ago
I nearly settled on OCaml. After AI warning me that proper work-stealing parallelism is a massive, sophisticated project to code properly, the 40 lines of OCaml code I wrote that beat available libraries is my favorite code file in years.
Nevertheless, once one understands lazy evaluation in Haskell, it's hard to use any other language. The log slowdown for conventional use of a functional data structure becomes a linear speedup once one exploits persistence.
int_19h|3 months ago
mbac32768|3 months ago
7thaccount|3 months ago
Kwpolska|3 months ago
I couldn’t believe this was an actual bug in opam, and I found it: https://github.com/ocaml/opam/issues/5373
I don’t think that’s an opam bug, it’s an issue with musl, and they just happened to build their binaries with it.
mbac32768|3 months ago
> * Ocamlfmt is pretty bad. It thinks it is writing prose. It will even put complex `match`es on one line if they fit. Really hurts readability.
I suggest configuring ocamlformat to use the janestreet profile for better defaults.
> * Optional type annotation for function signatures throws away a significant benefit of static typing - documentation/understanding and nice error messages.
People should be providing .mli files, but don't. That said, an IDE with type hints helps this enormously. The VS Code plugin for OCaml is the best experience for noobs, hands down.
> OPAM
yes
boppo1|3 months ago
kristianp|3 months ago
This made me chuckle. I've had that thought before, shouldn't the default be a vector on modern devices? Of course other collection types are available.
int_19h|3 months ago
But you can have a data structure that is more like vector under the hood while still supporting efficient copy-with-modifications. Clojure vectors, for example.
olivia-banks|3 months ago
systems|3 months ago
just to give an idea how bad, until recently, you could not just go to ocaml.org and download ocaml for windows, you had to either download one for mingw or wsl
so for many it was just not installable, i.e. for many we didnt have ocaml for windows, until very very recently
thaumasiotes|3 months ago
On the other hand, you could get ocaml for Windows from Microsoft ever since 2005.
mbac32768|3 months ago
One of the things people often neglect to mention in their love letters to the language (except for Anil Madhavapeddy) is that it actually feels UNIXy. It feels like home.
fithisux|3 months ago
LAC-Tech|3 months ago
timhh|3 months ago
* Compile time is only ok. On par with C++.
* Async has a surprisingly number of footguns and ergonomic issues.
* There's no good solution to self-borrowing or partial borrows.
* While using macros is fine, writing them is pretty awful. Fortunately you rarely need to do that. Relatedly it is missing introspection support.
* Sometimes the types and lifetimes get very complex.
But overall I still much prefer it to OCaml. The syntax is much nicer, it's easier to read, the ecosystem and tooling are much better, the documentation is much better, and it actively hates linked lists!
yodsanklai|3 months ago
Just taking the first example I can find of some auto-formatted OCaml code
https://github.com/janestreet/core/blob/master/command/src/c...
It doesn't look more a soup of words than any other language. Not sure what's hard to parse for humans.
zipy124|3 months ago
le-mark|3 months ago
This was my problem as well, the object oriented related syntax is just too much. ML of which caml is a version of, has really tight syntax. The “o” in ocaml ruins it imo.
StopDisinfo910|3 months ago
Considering it only impacts a fairly small subset of the language, could you explain how it supposedly ruins everything?
thw_9a83c|3 months ago
I agree. OCaml is a complex language with very beginner-unfriendly documentation. In fact, I would even say it's unfriendly to engineers (as developers). The OCaml community prefers to see this language as an academic affair and doesn't see the need to attract the masses. E.g. Rust is an example of the opposite. It's a complex language, but it's pushing hard to become mainstream.
codesnik|3 months ago
tempodox|3 months ago
Funny how tastes differ. I'm glad it has a syntax that eschews all the noise that the blub languages add.
chris_armstrong|3 months ago
* Windows support has improved to the point where you can just download opam, and it will configure and set up a working compiler and language tools for you[^1]. The compiler team treat Windows as an first tier target. opam repository maintainers ensure new libraries and library versions added to the opam repository are compiled and tested for Windows compatibility, and authors are encouraged to fix it before making a release if its reasonably straightforward
* debugger support with gdb (and lldb) is slowly being improved thanks to efforts at Tarides
* opam is relatively stable (I've never found it "buggy and surprising"), but there are aspects (like switches that behave more like python venvs) which don't provide the most modern behaviour. dune package management (which is still in the works) will simplify this considerably, but opam continues to see active development and improvement from release to release.
* the platform team (again) are working on improving documentation with worked recipes and examples for popular uses cases (outside of the usual compiler and code generation cases) with the OCaml Cookbook: https://ocaml.org/cookbook
There are other things I find frustrating or that I work around, or are more misperceptions:
* there isn't a builtin way to copy files because the standard library is deliberately very small (like Rust), but there is a significant ecosystem of packages (this is different to other languages which cram a lot into their standard library). The result is a lot of friction for newcomers who have to install something to get what they need done, but that's valued by more experienced developers who don't want the whole kitchen sink in their binary and all its supply chain issues.[^2]
* the type inference can be a bit of a love/hate thing. Many people find it frustrating because of the way it works, and start annotating everything to short-circuit it. I've personally found it requires a bit of work to understand what it is doing, and when to rely on it, and when not to (essentially not trying to make it do things it simply will never be able to do).[^3]
* most people use singly-linked lists because they work reasonably well for their use cases and don't get in their way. There are other data structures, they work well and have better performance (for where it is needed). The language is pragmatic enough to offer mutable and immutable versions.
* ocamlformat is designed to work without defaults (but some of them I find annoying and reconfigure)
Please don't take this as an apology for its shortcomings - any language used in the wild has its frustrations, and more "niche" languages like OCaml have more than a few. But for me it's amazing how much the language has been modernised (effects-based runtime, multicore, etc) without breaking compatibility or adding reams of complexity to the language. Many of these things have taken a long time, but the result is usually much cleaner and better thought out than if they were rushed.
[^1] This in itself is not enough, and still "too slow". It will improve with efforts like relocatable OCaml (enabling binary distribution instead of compiling from source everywhere) and disentangling the build system from Unixisms that require Cygwin.
[^2] I particularly appreciate that the opam repository is actively tested (all new package releases are tested in a CI for dependency compatibility and working tests), curated (if its too small to be library, it will probably be rejected) and pruned (unmaintained packages are now being archived)
[^3] OCaml sets expectations around its type inference ("no annotations!") very high, but the reality is that it relies on a very tightly designed and internally coherent set of language constructs in order to achieve a high level of type inference / low level of annotation, but these are very different to how type inference works in other languages. For example, I try and avoid using the same field name in a module because of the "flat namespace" of field names used to infer record types, but this isn't always possible (e.g. generated code), so I find myself compensating by moving things into separate modules (which are relatively cheap and don't pollute the scope as much).