Search code examples
ocaml

Why do multiple let statements inside a while body give a compile error?


I'm learning OCaml and I'm struggling with this snippet:

let found = ref false

let () =
  while not (Queue.is_empty q) && not !found do 
    let next = Queue.pop q
    let () = found := (next.subtotal == total)
  done 

The second let inside the while body doesn't compile, the error says 'suggested in'. Indeed, when I add a 'in' after the first let, and I remove the 'let' from the second line, it compiles.

But I don't understand why this is needed? Doesn't Ocaml normally interpret a new 'let' as if there were an 'in' after the last line? E.g. when I move those two lets outside of the while block, they compile fine.


Solution

  • OCaml makes the distinction between local definitions and module-level definitions. In a local definition like

    let g x =
      let y = 2 in (...)
    

    the name y is only defined to be 2 inside the (...) subexpression. In particular, this means that the name is only a temporary name and accessing it later will be an error

    let g x =
      let y = 3 in
      x + y
    let error = y (* the name y is unknown in this scope *) 
    

    Contrarily, module-level definitions like

    module N = struct
      let x = 0
      let y = 1
    end
    let ok = N.x (* [x] is a valid field of the module [N] *)
    

    defines new field of the current (sub)module, which will be always be here (even if they are shadowed later).