短路运营商的评估顺序和OCaml

时间:2014-05-23 15:33:07

标签: ocaml operator-precedence

在OCaml中,当使用let为短路运算符(&&||)分配别名时,它不再对操作数进行短路评估。 / p>

这不直观。这种行为的原因是什么?

请考虑以下代码:

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' *)

这也发生在let ... in上,因此let b = (&&) in b (f()) (g());;也会输出gf

2 个答案:

答案 0 :(得分:5)

这是因为&&是一个原始运算符,其语义与普通函数完全不同。实际上,(&&)或多或少等同于fun x y -> x && y,正如nlucaroni所解释的那样,在它们被应用之前会评估它的参数(以未指定的顺序,通常是从右到左,但你不应该依赖它)。

您可以使用ocaml -dlambda查看。这将启动一个解释器,它以您输入的每个命令的一种中间语言输出翻译。然后,您将得到以下结果:

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

lambda格式没有记录,但应该很清楚,eta扩展正在发生。

答案 1 :(得分:2)

评估不是懒惰的,因此{<1}}和f将在之前评估,它们将作为参数应用于您的函数。