Readit News logoReadit News
wk_end · 9 months ago
The title is a little inflammatory. The critique is specifically about Ocaml’s handling of let-bindings. AFAICT OP thinks the syntax sucks because:

1. there’s no marker to indicate the end of let scopes

2. functions are bound with the same syntax as constants

He asserts that this is confusing. In practice - for the many issues I have with Ocaml! - neither of these are actual issues, in my experience, once code formatting is applied.

An actual serious problem with Ocaml’s syntax is that matches don’t have a terminator, leading people to mess up nested matches frequently. Pair that with the parser’s poor error reporting/recovery and things can become unpleasant quickly.

nine_k · 9 months ago
Fortunately, the OCaml compiler is very modular, and there have been efforts to make things more... reasonable.

- Reason, a different syntactic frontend for regular OCaml: https://reasonml.github.io/

- ReScript, a language with OCaml semantics that compiles into: JS https://rescript-lang.org/ (I suppose it's a reincarnation of js-of-ocaml).

jey · 9 months ago
ReScript is better described as a descendant (and fork) of ReasonML aimed to fit into the JS ecosystem. In contrast to js_of_ocaml, ReScript prioritizes interoperability with existing JS code and APIs over interop with existing OCaml code, whereas js_of_ocaml takes the opposite approach. So people looking for an improved version of JavaScript or TypeScript should probably choose ReScript, but people who are porting an existing OCaml program might prefer js_of_ocaml.
obeavs · 9 months ago
Worth nothing that the former lead dev of ReScript left to create a WASM-first language call Moonbit (https://www.moonbitlang.com/). The language design is awesome and corrects a lot of the corners that they just couldn't get around in OCAML. A touch early, but really well done.
JoelJacobson · 9 months ago
I love the idea of Reason/ReScript. I hope they can figure out a way to work together and join forces somehow, the contributions to both repos seems to have faded over the last years, but maybe that's because the projects have stabilized, I don't know.

I've had lots of fun playing with Reason a few years ago. I created an interactive real-time visualization tool, to see a Regexp transform into a NFA to DFA to minimal DFA graph: http://compiler.org/reason-re-nfa/src/index.html It only works for basic regexes though.

BrawnyBadger53 · 9 months ago
I feel like ReasonML should have the capacity to help bridge the gap for people learning ocaml if it weren't so hidden.
RandomThoughts3 · 9 months ago
It's not more reasonable. It explicitely designed to look like JS which is, well, bad. Some of the choices are extremely annoying and overall useless like reintroducing parentheses for function arguments.

There is a reason - pun intended - it didn't take off at all with the community.

p4bl0 · 9 months ago
I was coming to say exactly this. I use OCaml a lot and never had a problem with lets. On the other hand, nested match with where you must either use parentheses or begin…end can be confusing for beginners and stays annoying forever.
soraminazuki · 9 months ago
> The title is a little inflammatory

I think you’re being generous. The example the author gave is awful because any language can be made illegible if you cram in complicated expressions with multiple levels of nesting into a single line. I’d say it’s outright flamebait.

pyrale · 9 months ago
> functions are bound with the same syntax as constants

Apparently, the author hasn't come around to understanding that functions are just another constant.

bvrmn · 9 months ago
TBF he has such notion:

> because a 0 arity function without side-effect is just constant.

sevensor · 9 months ago
> The title is a little inflammatory.

Xah Lee is not exactly known for moderation. If you’re not familiar, browsing the site may be worth your while. It’s full of inflammatory and sometimes bizarre takes, but I’d be hard pressed to argue that it’s ill informed.

the_af · 9 months ago
> If you’re not familiar, browsing the site may be worth your while

Not inclined to do this though, his site doesn't exactly seem easy to browse either. Maybe a reflection of his bizarre takes?

Do you have some examples of well-informed articles by him? I found one about "syntax vs semantics" that seems as inflammatory and ill-informed as TFA under discussion here. I'm not inclined to give this person much leniency...

RandomThoughts3 · 9 months ago
> An actual serious problem with Ocaml’s syntax is that matches don’t have a terminator, leading people to mess up nested matches frequently. Pair that with the parser’s poor error reporting/recovery and things can become unpleasant quickly.

Yes, it's clearly one of the syntax weak point. You can surround them with parentheses or begin ... end to make things explicit but the default is definitely error prone.

remexre · 9 months ago
i agree an autoformatter alleviates the let decl/expr in practice, especially for an experienced user; an autoformatter also fixes nested matches too ime.

however, my university has a mandatory class taught in ocaml, which i've ta'd for a few times; this is the _number one_ "the undergrad ta couldn't figure out my syntax error" issue students have

seanhunter · 9 months ago
Totally agree. In particular when I read #2 I was really scratching my head. It's a functional language - the thing on the left of the equals sign is a pattern. Apart from the argument you pass, patterns for functions look similar to patterns for constants precisely because in a functional language everything looks like a function. And everything looks like a function because just about everything is a function.

The match terminator end thing made me sad when I first saw this in Ocaml. So many languages (C, bourne shell, etc etc) have this exact same problem and it completely sucks in all of them. It's more debilitating in a functional language specifically because matches are more useful than say C case statements so you want to use them much more extensively.

I frequently want to do a pattern match to unpack something and then a further pattern match to unpack further - a nested match is a very intuitive thing to want. Yes you can normally unnest such a match into more complicated matches at the parent level but this is usually much harder for humans to understand.

...and if you had a marker for ending match scopes you could always just reuse that to end let scopes as well if you wanted to although I've literally never a single time run into that as a practical problem (although I haven't written that much OCaml you'd think if it was a real issue I would have banged into it at least once because I found a fair few sharp edges in my time with the language).

yawaramin · 9 months ago
> ...(C, bourne shell, etc etc) have this exact same problem...

Doesn't Bourne shell syntax have terminator keywords for all control flow structures? https://unix.stackexchange.com/a/256152

yodsanklai · 9 months ago
> leading people to mess up nested matches frequently.

Very often this leads to typing errors. Otherwise it's caught by autoformat (which everyone should be using). But even without that, this is one pitfall every OCaml developer is aware of.

I'm not arguing the syntax is perfect, but I wouldn't say it has a serious problem because of that. Never seen that being a problem.

pyrale · 9 months ago
Keyboards are also extremely error-prone. I can't count the times where I mistyped because of that. After each keystroke, people should type a "confirm" character in order to make sure of what they're doing.
laylomo2 · 9 months ago
The more I used ocaml the more I found beauty in the syntax. It’s very ergonomic in many ways:

1. It’s whitespace insensitive, which means I can code something up really messy and the code formatted will automatically fix it up for me.

2. In general there aren’t a ton of punctuation characters that are very common, which is great for typing ergonomics. Don’t get me wrong, there are still a lot of symbols, but I feel compared to some languages such as Rust, they’re used a lot less.

Beyond the syntax, there are a couple of things I really like about the language itself:

1. Due to the way the language is scoped, whenever you encounter a variable you don’t recognize, you simply have to search in the up direction to find its definition, unless it’s explicitly marked as “rec”. This is helpful if you’re browsing code without any IDE tooling, there’s less guessing involved in finding where things are defined. Downside: if the “open” keyword is used to put all of a module’s values in scope, you’re usually gonna have a bad time.

2. The core language is very simple; in general there are three kinds of things that matter: values, types, and modules. All values have a type, and all values and types are defined in modules.

3. It’s very easy to nest let bindings in order to help localize the scope of intermediate values.

4. It has a very fast compiler with separate compilation. The dev cycle is usually very tight (oftentimes practically instantaneous).

5. Most of the language encourages good practice through sane defaults, but accessing escape hatches to do “dirty” things is very easy to do.

6. The compiler has some restrictions which may seem arcane, such as the value restriction and weak type variables, but they are valuable in preventing you from shooting yourself in the foot, and they enable some other useful features of the language such as local mutation.

bloomingkales · 9 months ago
2. In general there aren’t a ton of punctuation characters that are very common, which is great for typing ergonomics. Don’t get me wrong, there are still a lot of symbols, but I feel compared to some languages such as Rust, they’re used a lot less.

I never really seen someone put that into words. I always feel a certain kind of weird when I look at a language with tons of punctuation (Typescript is good example).

seanwilson · 9 months ago
I think typing ergonomics are overlooked as well. CSS has the most verbose syntax for variables I've had to use regularly e.g. `var(--primary-color)` which I find unpleasant to type when experimenting. And I actually like the lack of brackets and commas in OCaml for function e.g. you write `add_numbers 1 2` instead of `add_numbers(1, 2)`. Brackets and commas in particular require you to navigate left/right a lot to add them in the right place while iterating and give confusing errors when you get them wrong.

Would be curious if there's work into a programming language that was optimized for minimal typing while iterating.

lolinder · 9 months ago
I feel the opposite—the typing ergonomics are better with a lower-punctuation language, but the reading ergonomics are substantially worse.

Punctuation is used in written human languages to provide assistance to our brain-parsers—like road signs that help navigate a sentence. Too much punctuation and it becomes a huge problem because it ceases to be meaningful, but have you ever tried reading a Roman inscription written with no spaces or sentence boundaries?

I think programming language punctuation serves the same role—it visually marks out how the parser is going to navigate the code, allowing the reader to use less mental effort repursing code that they initially misparsed. ML-style languages have a simpler syntax than the C family, which means there is some justification for having less assistive punctuation, but I've definitely struggled to navigate OCaml as a result of too little punctuation.

akkad33 · 9 months ago
The lambda syntax and default lambda parameters alone make typescript very hard to parse
pxeger1 · 9 months ago
I believe OCaml's syntax does suck, but I don’t think this article gives a compelling argument as to why. Missing an `in` turns a let expression into a top level binding and kicks a syntax error often a long way down the file, making it very hard to identify the cause. The relative precedence of let, if, match, fun, and the semicolon is unintuitive and hard to remember, making me want to add loads of unnecessary and ugly parentheses.

On the other hand, I like that there's little overloaded syntax, and the meaning of different characters is fairly consistent.

boccaff · 9 months ago
If anything, OCaml's error messages are something that sucks, especially for newcomers. The `Error: Syntax Error` message that points to an empty last line in the file leaves you doing the parser work, in a language that you don't understand.
the_clarence · 9 months ago
Worked on an ocaml codebase for two years. My advice is: choose a different language. It's just not a great dev experience in general
otabdeveloper4 · 9 months ago
> Worked on an X language codebase for two years. My advice is: choose a different language. It's just not a great dev experience in general.

I'm pretty sure it's "working on a codebase" that kills your soul, not the minutae of particular language choice.

eru · 9 months ago
Depends on what you compare it with, I guess. (I worked in OCaml and Haskell and other 'weird' languages professionally in different jobs for many years.)
akkad33 · 9 months ago
Fsharp is pretty good in teams f tooling at least when compared to other functional languages
davesnx · 9 months ago
Curious to know more, do you think can make a long-form of "why" and a detailed experience? If you have some time, would be massive to compare it with what's the same experience today
RandomThoughts3 · 9 months ago
I also worked on an ocaml codebase for a roughly similar time frame and found it extremely pleasant. Probably the best time I spent as a dev with working on an Ada project with a great architecture.
kamov · 9 months ago
What were the main issues you came across? What language would you prefer if you had to start from scratch and had the choice to go with anything else?
4ad · 9 months ago
Other commenters have already expressed their opinion about the shallowness and inadequatenessof the article, so I will touch on a different, more technical point.

The author doesn't understand why OCaml (and Haskell, and many HM-derived languages) have let ... in ... at all, as opposed to having, say, just lambdas. That's because of a feature of Hindley–Milner type systems called let-polymorphism[1].

This is hard to see in OCaml if you are not intimately accustomed with HM type systems because definitions always use let, but in Haskell it's immediately clear that something more interesting is happening because regular definitions do not use let.

F#, which has been heavily inspired[2] by OCaml got rid of the in, rather it uses indentation to do automatic in insertion[2]. OCaml does not want to be indentation-aware.

[1] https://en.wikipedia.org/wiki/Hindley–Milner_type_system#Let...

[2] https://fsharp.org/history/hopl-final/hopl-fsharp.pdf

user2342 · 9 months ago
Weak arguments in the article with badly chosen examples.

If one wanted to criticize OCaml syntax, the need for .mli-files (with different syntax for function signatures) and the rather clunky module/signature syntax would be better candidates.

_flux · 9 months ago
I actually rather like the mli-files. It's a nice file to read, with the documentation and externally available symbols only. However, the fact that the syntax is so different is a bit annoying.

Sometimes I wrote (haven't written OCaml for some time now..) functions like:

    let foo: int -> int = fun x ->
      ..
just to make them more similar to the syntax

    val foo: int -> int
in the module types.

armchairhacker · 9 months ago
The problem with mli files and counter-argument to “they’re good documentation” is that, with a few visibility annotations (`pub let`, etc.) they could be auto-generated. Then you don’t have to write your entire public interface twice (sans the inferred `let` types, but I already prefer to make those explicit in the `ml` because otherwise you get much more verbose type errors when they don’t align with the `mli`).
phplovesong · 9 months ago
I actully like the mli files. Its a separate place to describe the PUBLIC API, and a good place for documentarion. Now you dont clutter your code with lots of long comments and docstrings.
ubertaco · 9 months ago
This is such a weird complaint that it feels like engagement bait.

"Let x be equal to 4 in x * x" is a natural way to express a concept in English.

The equivalent OCaml code is:

    let x = 4 in
    x * x
I'm not sure how that qualifies as "sucks"?

In fact, the `in` makes OCaml's scoping rules some of the easiest to follow. This is valid OCaml code:

    let x = 4 in
    let y = 3 in
    let z = 2 in
    x * y * z

    let x = 5 in
    let y = 6 in
    let z = 7 in
    x * y * z
The phrasing of "let x = 4 in <this expression>" makes it explicit where x is defined as 4, vs where it's instead (in a different expression) defined as 5.

I have an easier time understanding scope in OCaml, which explicitly spells out its scoping rules in plain-English syntax, than I do in Rust or JavaScript, which use the deceptively-simple-looking braces but also wild concepts like lifetimes or hoisting.

yawaramin · 9 months ago
And for people who don't like writing so many 'in's, we also have 'and':

    let x = 1
    and y = 2
    and z = 3 in
    x * y * z
Which indicates that the binding of y can't refer to x and so on.

steinuil · 9 months ago
I've written a lot of OCaml and I always thought `let .. and .. in` indicated that the definitions were mutually recursive and that you could refer to y in x, like in `let rec .. and` or `type .. and`! That's surprising.
misja111 · 9 months ago
I tried out OCaml last year for solving the AOC puzzles. I managed to solve all of them in earlier years using Haskell or Scala, but this was the first time I gave up. It was not as much the syntax, it was the schism between the OCaml standard libraries and those from Jane Street that turned me off. Whatever I was searching for on the Internet, resulted in a mix of links to either of those libraries. It was confusing and very frustrating.
nobleach · 9 months ago
I get that. Having read Real World OCaml back when it was an O'Reilly book, I had a hard time not thinking Core was the defacto OCaml std lib. And its horrible documentation made me think the OCaml community was dead - or at least brain-dead. It appealed to one type of learner: Someone who just needs to see type signatures and has no interest in examples of how it could be used.

After reading OCaml From The Very Beginning my stance softened. Learning PURE OCaml is a must. (if you want to do AoC with it). You may find yourself bringing in Core or Base, after you've got a good idea of a solution.

It's definitely a fun language for doing AoC... but it can become extraordinarily frustrating when you hit a wall and all the StackOverflow answers assume Core.

yawaramin · 9 months ago
Yup the thing that people recommending Jane Street libraries to newcomers don't realize is that they are made by and for a well-established team of OCaml developers who have been extensively trained in how to use it in Jane Street. Outside of the warm protective bubble of Jane Street's tribal knowledge, it's a more difficult task to pick up and understand their libraries with their often minimalistic documentation.