"let in" chaining vs "let and in" expressions

Hi folks!

I’m new to OCaml and enjoying the learning experience a lot. I’m using the Cornell book, which I can wholeheartedly recommend to any newbies - it’s great.

While I was trying to solve a capture-the-flag a friend of mine came up with, I discovered that in some codebases multiple let-bindings were defined as such

let x = 40
and y = 2 in
x + y

as opposed to what I’m familiar with

let x = 40 in
let y = 2 in
x + y

I tried experimenting with it to find out what the difference between the two expressions is. As I understand it, it doesn’t matter semantically whether we use let-in chaining or let-and, as long as the definitions don’t depend on each other, i.e. in the expression let x = e1 and y = e2 in e3 the subexpression e2 must not depend on the binding for x. So let x = 40 and y = x + 2 in y would not work (utop gives an error for Unbound variable x). So when chaining let-in, each new binding that is created may access all the bindings which were created before it, whereas with let-and each binding is independent of the other bindings and cannot access them.

Another example of where let-and is necessary is for mutually recursive definitions such as

let rec even x = if x = 0 then true else odd (x - 1)
and odd x = if x = 0 then false else even (x - 1)

So I’d like to ask the following questions:

  1. Is my understanding of the difference between let-in chaining and let-and correct so far?
  2. Are there important bits that I missed?
  3. If we only need let-and for mutual recursion, why would we ever use it in situations where chaining multiple let-in expressions also works? Is it just personal taste or does it affect performance in any way?
  4. Related to 3.: If we can sometimes freely choose between let-in chains and let-and, what is considered most idiomatic/ what are best practices?

Thank you for your time!

3 Likes

Yes.

Apart from mutual recursion, let-and bindings allow you to express certain constructions very elegantly, eg let x = y and y = x in ... swaps x and y without needing an auxiliary variable. Another use of let-and is in the context of binding operators, where let-and is used as syntax for monoidal product operations.

Cheers,
Nicolas

15 Likes

Thank you for the clarification!

I found an interesting article which explains the bindings operators you mentioned in a very beginner-friendly way. For anyone interested, check out this blogpost about let*, and*, let+ and and+