Order of evaluation for short-circuit operators and let in OCaml

大城市里の小女人 提交于 2019-12-11 03:09:50

问题


In OCaml, when using a let to assign an alias to a short-circuit operator (&& or ||), it no longer short-circuits evaluation of the operands.

This is not intuitive. What is the reason for this behavior?

Consider the following code:

let f() = Printf.printf "f"; false;;
let g() = Printf.printf "g"; true;;
let a = (&&);;

f() && g();; (* outputs 'f' *)

(&&) (f()) (g());; (* outputs 'f' *)

a (f()) (g());; (* outputs 'gf' *)

This also happens with let ... in, so let b = (&&) in b (f()) (g());; also outputs gf.


回答1:


It's because && is a primitive operator whose semantics is quite different from a normal function. In fact, (&&) is more or less equivalent to fun x y -> x && y, which as explained by nlucaroni will evaluate its arguments before they are being applied (in an unspecified order, which happens to be usually right-to-left, but you should not rely on it).

You can see that by using ocaml -dlambda. This will launch an interpreter which outputs the translation in one of the intermediate languages of each command you enter. Then, you'll have the following result:

# (&&);;
(function prim/1044 prim/1043 (&& prim/1044 prim/1043))
- : bool -> bool -> bool = <fun>

The lambda format is not documented, but it should be clear enough that eta-expansion is happening.




回答2:


Evaluation is not lazy, so f and g will be evaluated before they are applied as arguments to your function.



来源:https://stackoverflow.com/questions/23833221/order-of-evaluation-for-short-circuit-operators-and-let-in-ocaml

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!