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
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