Evaluation order of application differs between labelled and optional arguments

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 ?

2 Likes

As you said the order of evaluation is not specified, and the order of evaluation is (somewhat) purposefully different in presence of optional arguments (to avoid code size blow up when fixing many optional arguments at the same time), see Tweak for evaluation order of labelled partial applications by lthls · Pull Request #10653 · ocaml/ocaml · GitHub .

1 Like

If you look at @garrigue’s comments (in particular Tweak for evaluation order of labelled partial applications by lthls · Pull Request #10653 · ocaml/ocaml · GitHub), you’ll see that there is indeed a bug (the evaluation of the argument shouldn’t be pushed inside a closure) and that the PR fixes it but Jacques wanted to also keep an optimisation that the PR removes.

4 Likes

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)

1 Like