OCaml 评估表达式,顺序?

OCaml evaluation of expression, order?

add 是 OCaml 内置的函数。

Exp:

# add 5 1;;
- : int = 6

我的问题:add 3 (add 5 3) 的求值顺序是什么?

# add 3 (add 5 3);;
- : int = 11

是先(add 5 3)求值为8,然后add 3 (8)求值为11?或者是add 3先求值成一个函数,然后(add 5 3)作为函数的参数(add 3)?

谢谢。

就其价值而言,OCaml 中没有内置名为 add 的函数。 (即,在 Pervasives 模块中没有这样的符号。)

$ ocaml
        OCaml version 4.06.0

# add;;
Error: Unbound value add

OCaml 中函数及其参数的求值顺序未指定。所以没有保证订单。

这在 Section 7.7.1 of the OCaml manual 中有记录。

如果您希望按特定顺序进行计算,可以使用 let 来计算每个子表达式:

# let add a b = a + b;;
val add : int -> int -> int = <fun>
# let temp = add 5 3 in
  add 3 temp;;
- : int = 11
# let tempf = add 3 in
  tempf (add 5 3);;
- : int = 11

为了完成 Jeffrey 的回答,这里是 add 的一个版本,它让您知道它何时被执行:

# let add a b =
    Printf.printf "Adding %d and %d...\n" a b;
    a + b;;

val add : int -> int -> int = <fun>

让我们看看实际效果。

# add (add 1 2) (add 5 8);;

Adding 5 and 8...
Adding 1 and 2...
Adding 3 and 13...

- : int = 16

所以在这里,第二个 add 首先被评估,但你不能真正指望它,因为它没有指定。

下面是使用本地 let 强制执行命令的相同示例:

# let x = add 1 2 in
  add x (add 5 8);;

Adding 1 and 2...
Adding 5 and 8...
Adding 3 and 13...

- : int = 16

现在使用部分应用程序。

# let add_3 = add 3 in
  add_3 (add 5 8);;

Adding 5 and 8...
Adding 3 and 13...

- : int = 16

当然,对于(纯)函数式编程,执行顺序并不重要,因为一切都是不可变的。但 OCaml 并非纯函数式,因此了解这些小技巧很有必要。 :)

OCaml 中参数的计算顺序未指定,这意味着它可以从一个编译器更改为另一个。

让我们创建一个分两个阶段求值的函数:

let mul a =
  Printf.printf "got a: %i\n%!" a;
  fun b ->
    Printf.printf "got b: %i\n%!" b;
    a * b

运行 这与 utop(或 ocaml)显示从右到左的评估:

# mul (mul 2 3) (mul 5 7);;
got a: 5
got b: 7
got a: 2
got b: 3
got a: 6
got b: 35
- : int = 210

可以引入let-in来强制求值顺序,导致不同的printfs顺序:

# let mul6 = mul (mul 2 3) in mul6 (mul 5 7);;
got a: 2
got b: 3
got a: 6
got a: 5
got b: 7
got b: 35
- : int = 210