The evaluation order of arguments of an application seems to differ between labelled and optional parameters.
For example, if we consider the following code:
let f ~x =
print_endline "fx";
fun ~y z -> x + y +z
let _ = f ~x:(print_endline "x"; 0) (print_endline "z"; 0)
The x argument seems to be evaluated first, then the application f ~x, and finally the last argument.
Thus, the program prints:
x
fx
z
However in the following code:
let g ?(x=0) =
print_endline "gx";
fun ~y z -> x + y +z
let _ = g ~x:(print_endline "x"; 1) (print_endline "z"; 0)
Only the last argument seems to be evaluated, as the program only prints:
z
While I believe the evaluation order is not specified in such cases, this difference seems strange. Is that really the desired behaviour or is it a bug ?
Even though the evaluation is indeed unspecified, I did expect it to be consistent in these cases.
As pointed out, the fact that the evaluation of the optional argument is pushed inside the closure seems particularly awkward. Wouldn’t the discussed optimization only be correct when optional arguments are actually defaulted?
(Though I’m not sure that is easily detectable at this point of the compilation, as optional arguments are already fixed)