Favorite Benefits of OCaml

Hello!

We’re looking to revise the Why OCaml pag, and we’d like to focus on the benefits of OCaml rather than the features, making it less technical and more engaging for newcomers.

What are your favorite things about OCaml? What would you tell a newcomer to convince them to try OCaml?

Thanks for your help!

8 Likes

I am a newbie so perhaps might be wrong. some of my favorite things are (1) Ability to use both code and data as values and then composing logic with railway programming techniques (|> and ->) brings clarity (2) Powerful collections library (3) ability to organize code with modules and (4) Ability to write frontend and backend applications with js_of_ocaml, reason, rescript and (5) Powerful concurrency library like Lwt.

3 Likes
  • Fast compiler; fast iteration speed, easy to try out experiments and refactor quickly
  • REPL-driven workflow possible; one of the rare compiled languages that allows you to start a REPL session and interactively start building a Gtk+ GUI
  • Strength of the type system is tempered by practicality and provides just enough leverage that many errors can be ruled out with simple, elegant types; doesn’t go overboard with type safety features
  • Surprisingly still rare among compiled languages: provides named and optional arguments, a huge benefit for maintainable code
  • Lot of attention given to backwards compatibility in general; people report that decades-old code still compiles in modern OCaml versions, just with more safety warnings.
16 Likes

When I was looking around, only OCaml language had all of the following:

  • ML-like type system
    • Algebraic data types
  • Immutability first
  • Pattern matching
  • Type inference
  • Fast compilation speed
  • All of the above enables a fast, iterative, ‘if it compiles, then it mostly works’ workflow, and makes refactoring a breeze, while keeping everything practical. This advantage cannot be overstated!
  • Produces a single, reasonably-sized binary for deployment
  • Has a robust, mature JavaScript compiler, which produces reasonably-sized JavaScript output (OCaml technically has 2 or 3 of them, depending on who you ask!)
  • Mature tools around build, packaging, testing
3 Likes

The page is quite good already. But I believe it’s an excerpt from Real World OCaml, so maybe targeting an already convinced audience.

Although I’m still learning and haven’t made up my mind fully about OCaml, if I were to “sell” it, I would put forward these arguments:


Have you noticed that the frontend development world has embraced the functional paradigm to face complexity?

What if you could apply the same idioms to your backend?


  • fast feedback loop : like Go
  • fast execution speed : comparable to Go/Rust/C++
  • ease of use : efficient GC, small memory usage! Like Go, unlike Java (memory wise).
  • concise syntax : terse like Python but with inferred type-safety!
  • strong type system : comparable to Rust. If it compiles, it probably works. No nulls! Exhaustive pattern matching!
  • flexible: if the functional paradigm is not a good fit, you can go imperative
  • interactive : REPL allows you to poke at your program while iterating

Taking a step back, I’m not sure I’ve actually answered the question of benefits vs features though :slight_smile:

But to convince another programmer, I think it’d be useful to explain where OCaml fits in by comparing it to other programming languages.

I had heard about OCaml years back. In my mind at the time, I somehow associated the OCaml name with an antiquated technology. Something from the past not worth looking into.

Hope that’ll give you food for thought :slight_smile:

4 Likes

My initial draft actually was along the same lines:

What would you tell a newcomer to convince them to try OCaml?

It would depends on where the newcomer comes from.
It compiles nearly as fast as Go does, and also produced a single binary for deployment, but has a better type system and error handling mechanisms.

But I ended up with what felt like bad-mouthing other languages.

Your approach is better. At least a section on that page might go like “OCaml provides you best of all” or something.

EDIT: Most of the following points are the same as @benjamin-thomas 's. That’s what I get for skimming a post.

  • compiles nearly as fast as Go
  • runs as fast as Go and Rust
  • produces single binary like Go
  • immutable first, like Clojure, Haskell, unlike Go, but also doesn’t involve a whole lot of ceremony in order to employ mutability
  • with type inference, code looks as clean as Python’s, but guarded by a strong type system
  • robust type system [Haskell?], making refactoring a breeze. If it compiles, it works.
  • pattern matching ensures edge cases don’t get left out. Better than switch statements.
  • Has better error handling than most, but also has exceptions with extra guards, because of pattern matching

There is also the problem of which class of newcomers the page wants to cater to.

For example, comparing features with those of Haskell may seem futile when a large swathe of programmers - beginners or experienced - use JavaScript or Java.

Some features also may not feel significant to a person until they have felt the pain of the lack of it in another language.

1 Like

What thing that seems missing from the page and which I especially enjoy is that, for the most part (no objects, no polymorphic variants), the semantics and the execution model of OCaml are straightforward. It does not take long to explain to someone what values are, how they are represented, what the time complexity of the operations is, and so on. There are not that many languages that enjoy this property.

Let us not propagate this myth any further. At most, what we can honestly say is that, if it compiles, it is memory-safe. But being memory-safe is very very far from working. I have graded sufficiently many students to know that, just because an OCaml program compiles, it does not mean that it will not put the world on fire (or at least the computer it is running on).

5 Likes

I agree. I forgot to qualify it with ‘mostly works’, like I did in my previous post in this thread.

I think I wanted to say “A compiled program in OCaml gives you a higher confidence than one in [insert a popular language].”

But your point stands.

I also never understood “if it compiles, it works”. One has to write a precise specification of what “works” means and than program against that specification and potentially use formal methods to show that the program adheres to the specification. If it does, then it “works”.

I’m also with @silene on that one but I guess the sentiment can be understood if you come from dynamically typed languages where lots of silly mistakes only happen at runtime.

E.g. from php where your app can work perfectly for a long time until it hits a path where you call a function with a typo and thus explodes in your hands. Or from JavaScript where you suddenly index an object member that doesn’t exist.

Since you no longer see these silly mistakes it likely gives you the impression than once it compiles, it works.

Unless you have a bug in your specification. Having specifications is not a panacea either. But it gives the nice property of having something to pit against your program. Both the program and the specification inform each other and may need tweaking to reconcile their views.

3 Likes

Yeah, I guess we can say it works type-wise. :slight_smile:

Yep, in the world of formal verification it’s accepted that at some point one has to trust someone, otherwise one must prove specs ending up with a hierarchy of proofs. It’s not a panacea but at least it’s defined what “works” means so one can reason about it. Without a spec, a program neither works nor doesn’t work, IMHO.

1 Like

To me, the catch phrase “if it compiles it works” is a very real thing. The system you code against gives you friction, and in return you get benefits/garanties. Is worth it? Only the programmer can tell.

I get this feeling even more when coding with Haskell, although I’m only learning and scratching the surface here.

I don’t think any programmer would ever assumed a programming language could protect you from logic bugs :slight_smile:

“You’ll get less runtime errors” is probably more accurate, but even then…

I’ll give you a couple of examples.

This Java code compiles fine and will fail at runtime with a NullPointerException:

package org.example;

class Hello {
    Integer counter;
    public Hello() {
    }

    void sayIt() {
        counter++;
        System.out.printf("Hello world! (%d)", counter);
    }
}

public class Main {
    public static void main(String[] args) {
        Hello hello = new Hello();
        hello.sayIt();
    }
}

Golang chose to ignore these kinds of problems by enforcing default values (an uninitialized string is “”, an uninitialized int is 0, etc.)

Personally, I found this to be not a good solution because the concept of “nothingness” is still useful/required for database work. This forces you to deal with pointers to express nothingness and you’re back at square one.

TypeScript’s type system can actually lie to you and I see that googling “TypeScript lie” returns a few interesting blog posts.

Anyhow, all these little things add up, and it’s quite refreshing to have a sound type system giving you the feeling that:

If it compiles, it (probably*) works :slight_smile:

P.S. I’m pretty sure I’ll find a few warts with OCaml along the way, but then again, at this stage, I’m pretty sure I’ll find less of them compared to other languages.

1 Like

It’s true that strong typechecking mostly gives you memory safety. However, there are further benefits to be had. For example, having well-differentiated types means that logic problems due to the confusion between variables and arguments are more rare.

Furthermore, a lot of the ‘if it compiles, it works’ experience comes from the degree to which you apply functional paradigms. Using functional data structures and avoiding mutable state has a performance cost and often a syntactic one as well, but it enforces a clear division between computation stages and isolates the impact of every function. Because OCaml supports both functional and imperative paradigms, you will get much more of the ‘if it compiles, it works’ experience when you stick to functional paradigms.

3 Likes

I couldn’t fall back asleep after being awoken by my 6-year old and in my addled brain started imagining if we rewrote the “Why OCaml” page built around the language’s pain points? :laughing: :laughing: :laughing:

E.g.:

  • Do you like inscrutable error messages? We’ve got them!

  • Specify your build configuration as sexps for idiosyncratic, historical reasons!

  • We’ve separated the package management and build systems for OUR convenience!

  • Type signatures are all the documentation you’ll ever need or get!

And, yet, you’re going to fall in love with this language as you quickly become an order of magnitude more productive than you currently are. That’s how great OCaml is!

12 Likes

This is a hilarious take, but highly agreeable. I would sneak in something about not being able to print your values without jumping through a circus of tools. It’s really just using ppx show. Fortunately it’s mostly just tooling.

But other than that, the language itself is a snack!

2 Likes

I’ve been using Haskell for many years, so I’m quite fond of many typical FP features. But what I especially like in OCaml so far is separate .mli interface files with only type signatures.

I like focusing on high-level details first, and being able to just quickly read type signatures of API with their description without diving into low-level implementation details is so nice!

7 Likes

Wow! Thank you all for these great responses! Keep them coming! It will be so much help when revising the documentation.

2 Likes

I’d like to add:

  • blazing fast bytecode interpreter for quick prototyping and scripting. I use compilation to native code only when really needed.
  • support of mixed functional and imperative programming
  • full OCaml language available in Javascript

Regards,
Ingo

3 Likes