I would expect let...in...
to have the following syntax
let binding = expression in expression
and the block goes as far to the right as possible.
In your example, the OCaml parser expects
let y = 2 in y + 1, 4
to be an expression and parses it as (3, 4)
successfully.
An equivalent of your example with explicit brackets is
let p = (let x = 1 in x + 1, (let y = 2 in y + 1, 4))
If you would like to return final result (2, 3, 4)
, you should put a bracket to stop let...in...
block in the appropriate place:
let p = let x = 1 in x + 1, (let y = 2 in y + 1), 4