Having seen "A tour of Elm,"[0] I really prefer that style. The left-hand side (what English readers read first) is an explanation of the concept, then the right side is the code, and the explanation gives you enough details to complete the code.
This introduction doesn't really explain anything, as I guess it assumes you've learned OCaml elsewhere and are just here to practice.
I tried the first exercise, and it felt more like a math problem than an exercise to teach a programming concept:
>Suppose that a variable x exists and is an integer.
>Define a variable x_power_8 that uses three multiplications to calculate x to the power of 8. The only function you are allowed to call is the (*) operator.
>Hint: use auxiliary variables.
So, at first I thought I was supposed to just call multiply eight times, and then I realized that they said you can only call multiply three times. So, you're supposed to do let a = x * x; let b = a * a; let x_power_8 = b * b. But that feels really contrived to me and not like anything I'd write in a real application, even a toy one. If the idea is teaching variables, why not just ask me to declare a variable that represents x plus 1?
This is a much better starting point: https://ocaml.org/docs
Using the search engine of your choice, you can find many more sources just looking for "learn ocaml".
Indeed the link is a not an introduction to OCaml but a demo instance of Learn-ocaml which is framework for building online exercise websites to complement (online or physical) lectures. This is why the instance is hosted on the OCaml Software Foundation website rather than ocaml.org: the demo is not targeted to learners but to teachers.
a, b variables are just used for computing x_power_8, you don't need them outside of this scope. I think the point of the exercise is to use variable binding, though I agree the website doesn't explain much
Context is needed... at least some explanation or bridge examples, like... why and what do I need to navigate this particular web landing page.
Website feels like an author exercise in ocaml for js web plugin.
If that bothers you, you shouldn't be learning ocaml. Look at the latest stack overflow developer surveys. A vast majority of developers and real applications never touch ocaml.
That's not what OCaml is like, at all. You clearly hate it, for whatever reason. Fine, have it your way. But popularity contests on SO are not an argument and they explain nothing.
At Rust Chipotle, they have strict rules about the ingredients for your burrito. "White rice with medium salsa, sir? Absolutely not!". You see, medium salsa only goes with brown rice, and you also need to have beans or nothing works. Under no circumstances will they allow you to construct the burrito you think you want, no matter how much you think you want it.
Meanwhile, at OCaml Chipotle you can have whatever you like, and it always turns out awesome. But once a month you go for lunch and they'll refuse to make you a bowl, refuse to tell you why, and refuse to let you leave. And when you try to get help from a passerby after being trapped in the store, you realize there's nobody nearby who you can ask.
But arguably F# (whose original name was OCaml.NET) is underrated. It improves on OCaml in a number of areas (better pattern matching, computation expressions, namespace support) but more importantly, F# solves OCaml’s biggest problems: lack of decent libraries and subpar tooling.
With F# you get instant access to thousands of high quality NuGet packages which includes everything from fast web servers to highly performant json deserialisation, and you can use some of the best IDEs, tooling and debugger around (JetBrains Rider is outstanding IMO).
F# suffers from the Microsoft association unfortunately, even though Microsoft barely cares about it and provides minimal support for it, most good things about F# are developed and maintained by the community. But the perception exists, and many think it’s still Windows only
I’ve recently been doing a lot of F# development, I do my work on a Mac, using Rider and OCI dev containers, and the code is deployed on Kubernetes, and honestly I don’t remember the last time I enjoyed a programming language and development tooling so much.
But F# seems to be a real beauty.
In general though I prefer the .NET runtime than the JVM in its current state - you can go a little bit lower level when required in hot code without going unsafe (value types, spans, etc).
https://www.youtube.com/playlist?list=PLre5AT9JnKShFK9l9HYzk... https://softwarefoundations.cis.upenn.edu/
A great resource for those looking to learn Rocq.
___
Typo in GP: "fun" instead of "fund"
I know some people dislike the fact that F# lacks OCaml's functors, but I can see why they weren't included. Due the the way F# integrates .NET classes/objects, I can accomplish more or less the same thing that way. In some ways I prefer it - a class/type full of static methods has the same call syntax as a module full of functions, but gives me the option of overloading the method so it'll dispatch based on argument types. Having everything that's iterable unified under IEnumerable/Seq is nice, too.
Having said all that, I still enjoy OCaml a ton. One thing I wish I could have is F#'s updated lightweight syntax brought over to OCaml. I think ReasonML is great, but after using it for a while I realized that what I really want isn't OCaml that looks more like JavaScript. What I want is OCaml that looks like OCaml, but a little cleaner. F# gives me that, plus, via Fable, compilation to JS, TypeScript, Python, and Rust. And via the improved native AOT compilation in .NET 9, I can build fast and reasonably small single-file executables.
Despite all that, I still try to dive in OCaml whenever it's a decent fit for a problem for the problem I'm trying to solve. Even if it's a little quirky sometimes, it's fun.
IMO, a language without proper modules, GADTs, or (now) an effect system, does not seem to me like it could plausibly be described as "essentially OCaml". Your point about having ad hoc polymorphism (outside of an object system) is another good point about why F# really is not OCaml on .NET.
Not to mention the difference of being trapped in (or having the luxury of, as you prefer) .NET vs. compiling to native binaries.
Glad you like F# tho!
I’m been on the JVM for 20+ years, but an opportunity came up to leverage some of my other experience to get some CLR work… and I dove in.
I mentioned in a top-level comment that F#'s "lightweight" syntax is basically what I want when I use OCaml. I know ReasonML is a thing, but if I'm writing OCaml I don't want it to look more JavaScripty - I prefer syntax like "match x with" over "switch(x)" for pattern matching, for example.
I know some people dislike the way F#'s newer syntax makes whitespace significant, and that's fair. But the older verbose syntax is there if you need or want to use it. For example, something like
let things =
let a = 1 in
let b = 2 in
let c = 3 in
doSomething a b c
should still work in F# like it would in OCaml.It's actually not that far off. For definitions that don't need to be self-referential you can use 'and':
let things =
let a = 1
and b = 2
and c = 3 in
do_something a b c
There are a few other places I prefer F#'s syntax, but overall it's not the reason I'd pick F# over OCaml for a project. It's usually mostly about needing to integrate with other .NET code or wanting to leverage .NET libraries for specific use cases.
Can't lose either way - they're both a please to work with.
Now after almost a decade with Elixir, used to functional patterns and immutable data access, I followed a course on compiler construction in OCaml [1] and it felt surprising easy and straight forward, while my attempts using regular imperative languages feel like I’m wasting time on bureaucracy and boilerplate (i.e. in C, Rust or Python) - pattern matching is such an amazing feature.
https://doc.rust-lang.org/rust-by-example/flow_control/match...
Pretty concise code: Go code is full of `if err != nil {...}` song and dance and they seem pretty committed to keeping it that way. Java is stuck with decades of decisions and libraries made in their early days because they can't break backward compatibility. Eg, all the standard library collection types are mutable. And of course, both of them have the 'null pointer' problem, which OCaml doesn't.
Meanwhile OCaml has had the same main type-level tools (record types, variant types) and techniques (pattern matching, first-class functions) since the very beginning and those are still the workhorse till this day.
Certainly better perf: I'd say that really depends on how much tuning has been done. OCaml applications by default are fairly performant and with OCaml 5's multicore support and effect handlers will unlock even more performance wins.
Languages with immutability/lazy seq/etc support built in can be tuned faster than a library (compiler help around sequences/streams rather than pure library based ones), and again the lack of stack types can make some of these immutable collections much slower/take up more memory than other language targets. There's algorithms I can't use in Java which I can use in .NET/Rust/C++/etc without memory penalty or lots of unsafe/hacky code.
Have you worked in language with immutable collections by default? It's night and day -- no more defensive copies, no more weird ImmutableList wrappers (Guava) which will (interface-wise) say they're mutable but will throw at runtime, no worrying about multithreading, cheap subsequences, etc. etc.
The difference is so stark that I would literally choose a worse[0] language(!) over a better one if it had immutable collections by default.
EDIT: Since you mentioned Java in a sibling comment -- give Scala a try and try working with the collections there.
[0] Within reason, of course :)
Aside from FP, the Ocaml type system is better than the mentioned ones. From one hand type inference means you have to write out types much less, and from the other hand the type system is more powerful and lets you express more things than Go/Java.
Really the only reason I can think to use OCaml over Rust is the compile time, which is quite impressive and significantly better than Rust's. But I don't think that's enough to put up with the other downsides.
I don't think the borrow checker is a factor. OCaml has aspects that are equally painful to learn.
Also if you know Rust you won't really learn much by learning OCaml except "oh that's where that Rust feature came from". Rust stole all the good features from OCaml.
If you haven't learnt anything like it, yes.
> most things can be done in imperative langs like Go/Java with pretty concise code
Which is why learning OCaml will make you a better programmer even if you then go back to Go/Java. You'll most likely never learn how to do those things without taking that step.
> and certainly better perf.
If you implement the same algorithm in both, it will be faster in Java. But you're more likely to find the better algorithm working in OCaml.
Look at the latest stack overflow developer surveys. It will tell you how much the international community chooses to use (or not) ocaml. To your question, that's people deciding whether it's worth learning.
For you and I maybe, but no. This is the HN bubble speaking. Most people learn a programming language to get a job or to do something they want to do.
I learn CS for fun too but I hold no illusions about the rest of the world.
"But decided against since Java had an ecosystem, tooling and really good performance."
Correct. Ocaml is not practical for projects or businesses. That's why you didn't pick it.
I mostly work with JS and last month picked up learning Zig and building things with it. Zig ecosystem is still early but fun to play around, plus the community folks are helpful with answering my noob questions