Advantage of `let rec` bindings vs regular `let` bindings in OCaml

ocaml

Solution

As I stated already in my comment, it seems that by using `let rec`, you avoid creating more closures. To inspect this, I created two slightly different files shown here:

`test1.ml` has the "usual" way without `let rec`:

let test1 x =
    let x = 5 in
    let w () = x + 1 in
    let n () = x + 1 in
    w () + n ()

On the other hand, `test2.ml` uses `let rec`:

let test2 x =
    let x = 5 in
    let rec w () = x + 1 
    and n () = x + 1 in
    w () + n ()

I then `ocamlc -dinstr`'d both files (i.e. I generated bytecode for both files) and obtained the following:

For `test1.ml`, I got:

    branch L2
L3: envacc 1
    offsetint 1
    return 1
L4: envacc 1
    offsetint 1
    return 1
L1: const 5
    push
    acc 0
    closure L4, 1
    push
    acc 1
    closure L3, 1
    push
    const 0a
    push
    acc 1
    apply 1
    push
    const 0a
    push
    acc 3
    apply 1
    addint
    return 4
L2: closure L1, 0
    push
    acc 0
    makeblock 1, 0
    pop 1
    setglobal Closuretest!

The file `test2.ml` resulted in the following:

    branch L2
L3: envacc 3
    offsetint 1
    return 1
L4: envacc 1
    offsetint 1
    return 1
L1: const 5
    push
    acc 0
    closurerec 3 4, 1
    const 0a
    push
    acc 1
    apply 1
    push
    const 0a
    push
    acc 3
    apply 1
    addint
    return 4
L2: closure L1, 0
    push
    acc 0
    makeblock 1, 0
    pop 1
    setglobal Closuretest2!

From a Caml Virtual Machine — Instruction set Document (unfortunately, I don't know if it even is the official one, but it looks reasonable), it seems that the instructions `closure` and `closurerec` generate a closure on the stack. As you can see, the bytecode for `test1.ml` generates 3 closures in total, while `test2.ml` only generates two closures (one via `closurerec`).

I am no assembly guru, but you can test `ocamlopt -S filename.ml`, so that the compiler leaves (and does not delete) the assembly (then in `filename.s`), where you can possibly spot analogous differences, as well.

Problem

This question is sort-of a follow-up question to this SO question: How to make a covariant observable in OCaml The accepted answer's author has (casually) noted that using `let rec` to bind two independent values would be more "economical" than two separate `let` bindings. ``` let make x = let queue = Queue.create () in let obj = x in let watch f = Queue.add f queue in let notify () = Queue.iter (fun f -> f x) queue in { obj; watch; notify; } ``` vs ``` let make x = let queue = Queue.create () in let obj = x in let rec watch f = Queue.add f queue and notify () = Queue.iter (fun f -> f x) queue in { obj; watch; notify; } ``` Was his statement correct? If so, why is the second version more "economical"?

Original source