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)
的参数?
谢谢。
答案 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