在Haskell中,let / where构造中的声明顺序无关紧要,例如:
f x = let g1 x y = if x>y then show x else g2 y x
g2 p q = g1 q p
in ...
g2
在声明之前g1
中使用的地方。
但这不是Ocaml的案例:
# let a = b in
let b = 5 in
a;;
Warning 26: unused variable b.
Error: Unbound value b
有没有理由说OCaml的行为不像Haskell?如果没有前瞻性声明,这个功能对我来说似乎很有用。
是因为OCaml中的严格评估,还是Haskell中的懒惰?
答案 0 :(得分:18)
OCaml使用“let rec”来指示组中的绑定何时可以相互引用。如果没有额外的“rec”,绑定必须是自上而下的顺序。有关详细信息,请参阅http://caml.inria.fr/pub/docs/manual-ocaml/expr.html处的“本地定义”。
答案 1 :(得分:7)
不严格,但这是同一问题的症状。
Ocaml不是纯粹的功能,也就是说任意函数调用可以执行任意I / O.这要求他们以可预测的顺序运行,这需要严格和你已经注意到的订购。
答案 2 :(得分:5)
在Haskell中,这不是因为懒惰的评估。确定哪个名称是指在编译时发生的事情,无论如何都没有执行任何事情(严格或懒惰)。请记住,在Haskell中,您只是编写数学定义,而不是按顺序执行的命令。你写这些定义的顺序无关紧要。不管你说
a = expr1
b = expr2
或
b = expr2
a = expr1
表示a
定义为expr1
,b
定义为expr2
。
我不知道任何OCaml,所以不能对此说些什么。
答案 3 :(得分:-1)
Haskell取消了古老的let
与let rec
之间的区别。
一个体面的编译器可以很好地看到它是一个简单的let还是一个包含相互递归定义并且可以相应地行动的。
(我想知道ML编译器如果以let rec
开头然后只有非递归定义会做什么。当然,当进行一些重构时,这个let / let rec是一个令人讨厌的障碍。)