Order of evaluation for short-circuit operators and let in OCaml

ocaml, operator-precedence

Solution

It's because `&&` is a primitive operator whose semantics is quite different from a normal function. In fact, `(&&)` is more or less equivalent to `fun x y -> x && y`, which as explained by nlucaroni will evaluate its arguments before they are being applied (in an unspecified order, which happens to be usually right-to-left, but you should not rely on it).

You can see that by using `ocaml -dlambda`. This will launch an interpreter which outputs the translation in one of the intermediate languages of each command you enter. Then, you'll have the following result:

# (&&);;
(function prim/1044 prim/1043 (&& prim/1044 prim/1043))
- : bool -> bool -> bool = <fun>

The `lambda` format is not documented, but it should be clear enough that eta-expansion is happening.

Problem

In OCaml, when using a `let` to assign an alias to a short-circuit operator (`&&` or `||`), it no longer short-circuits evaluation of the operands. This is not intuitive. What is the reason for this behavior? Consider the following code: ``` let f() = Printf.printf "f"; false;; let g() = Printf.printf "g"; true;; let a = (&&);; f() && g();; (* outputs 'f' *) (&&) (f()) (g());; (* outputs 'f' *) a (f()) (g());; (* outputs 'gf' *) ``` This also happens with `let ... in`, so `let b = (&&) in b (f()) (g());;` also outputs `gf`.

Original source