OCaml评估表达方式,顺序?

时间:2018-07-04 21:54:45

标签: expression ocaml evaluation

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)的参数?

谢谢。

3 个答案:

答案 0 :(得分:7)

对于它的价值,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

答案 1 :(得分:3)

仅需完成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并不是纯粹的功能,所以这些小技巧很容易知道。 :)

答案 2 :(得分:0)

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