My old notes on ML say that
let (๐ฃโ, โฆ , ๐ฃโ) = (๐กโ, โฆ , ๐กโ) in ๐กโฒ
is a syntactic sugar for
(ฮป ๐ฃโ. โฆ (ฮป ๐ฃโ. ๐กโฒ)๐กโ โฆ )๐กโ
and that
let (๐ฃโ, ๐ฃโ) = ๐ก ๐กโฒ in ๐กโณ
is equivalent to
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = snd ๐ฃ in
let ๐ฃโ = fst ๐ฃ in
๐กโณ
where
๐ฃ
(with or without a subscript) stands for a variable,๐ก
(with or without a sub- or a superscript) stands for a term, andfst
and snd
deliver the first and second component of a pair, respectively.I'm wondering whether I got the evaluation order right because I didn't note the original reference. Could anyone ((confirm or reject) and (supply a reference))?
It shouldn't matter whether it's:
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = snd ๐ฃ in
let ๐ฃโ = fst ๐ฃ in
๐กโณ
Or:
let ๐ฃ = ๐ก ๐กโฒ in
let ๐ฃโ = fst ๐ฃ in
let ๐ฃโ = snd ๐ฃ in
๐กโณ
Since neither fst
nor snd
have any side-effects. Side-effects may exist in the evaluation of ๐ก ๐กโฒ
but that's done before the let binding takes place.
Additionally, as in:
let (๐ฃโ, ๐ฃโ) = ๐ก ๐กโฒ in ๐กโณ
Neither ๐ฃโ
nor ๐ฃโ
is reliant on the value bound to the other to determine its value, so the order in which they're bound is again seemingly irrelevant.
All of that said, there may be an authoritative answer from those with deeper knowledge of the SML standard or the inner workings of OCaml's implementation. I simply am uncertain of how knowing it will provide any practical benefit.
As a practical test, running some code where we bind a tuple of multiple expressions with side-effects to observe order of evaluation. In OCaml (5.0.0) the order of evaluation is observed to be right-to-left. We observe tthe same when it comes to evaluating the contents of a list where those expressions have side-effects as well.
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (a, b, c) = (f (), g (), h ()) in a + b + c;;
h
g
f
- : int = 6
# let f () = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let (c, b, a) = (h (), g(), f ()) in a + b + c;;
f
g
h
- : int = 6
# let f _ = print_endline "f"; 1 in
let g () = print_endline "g"; 2 in
let h () = print_endline "h"; 3 in
let a () = print_endline "a" in
let b () = print_endline "b" in
let (c, d, e) = (f [a (); b ()], g (), h ()) in
c + d + e;;
h
g
b
a
f
- : int = 6
In SML (SML/NJ v110.99.3) we observe the opposite: left-to-right evaluation of expressions.
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (a, b, c) = (f(), g(), h())
= in
= a + b + c
= end;
f
g
h
val it = 6 : int
- let
= fun f() = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= val (c, b, a) = (h(), g(), f())
= in
= a + b + c
= end;
h
g
f
val it = 6 : int
- let
= fun f _ = (print "f\n"; 1)
= fun g() = (print "g\n"; 2)
= fun h() = (print "h\n"; 3)
= fun a() = print "a\n"
= fun b() = print "b\n"
= val (c, d, e) = (f [a(), b()], g(), h())
= in
= c + d + e
= end;
a
b
f
g
h
val it = 6 : int