Ocaml中参数的求值顺序

3
我希望了解为什么OCaml会从右到左评估调用,这是FP原则吗?或者对于FP语言来说根本不重要?
快速排序示例:
let rec qs = function
    | [] -> []
    | h::t -> let l, r = List.partition ((>) h) t in
    List.iter (fun e -> print_int e; print_char ' ') l; Printf.printf " <<%d>> " h;
    List.iter (fun e -> print_int e; print_char ' ') r; print_char '\n';
    (qs l)@(h::qs r)

在我的例子中,首先评估的是对 (qs r) 的调用,然后是对 (qs l) 的调用,但我期望它们的顺序是相反的。
# qs [5;43;1;10;2];;
1 2  <<5>> 43 10 
10   <<43>> 
     <<10>> 
     <<1>> 2 
     <<2>> 
- : int list = [1; 2; 5; 10; 43]

编辑:

来自https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora029.html

在Objective CAML中,参数的求值顺序未指定。目前,所有Objective CAML的实现都按照从左到右的顺序对参数进行求值。但是,如果将来的语言版本修改了实现,利用这个实现特性可能会变得危险。


@RichouHunter 看看我的吧 :) 在接下来的几个月里它仍然会有0票。 - Oleg
@Oleg 你为什么期望这个问题会有一些投票呢?如果你只是在搜索栏中输入了“[ocaml] order evaluation”,你就可以找到这个:https://dev59.com/fpbfa4cB1Zd3GeqPrUUw#36746891 或者这个 http://stackoverflow.com/questions/35548589/functions-calls-order-in-ocaml/35548754#35548754。这是我搜索的方式:http://stackoverflow.com/search?q=%5Bocaml%5D+order+evaluation - Lhooq
1
对于@RichouHunter,尽量在自己提问之前查找是否已经有人提出了同样的问题。通常,如果看起来像是一个琐碎的问题,就会有人回答它。 - Lhooq
题目类似于“在OCaml中返回列表的反向顺序的函数”,不要让我阅读它们的正文,这并不能提示它是关于参数求值顺序的问题。是的,我的问题是重复的,我的错因为我在谷歌上搜索了这个:https://www.google.de/search?q=order+of+ocaml+argument+evaluation&oq=order+of+ocaml+argument+evaluation&aqs=chrome..69i57j69i60l3.10135j1j7&sourceid=chrome&ie=UTF-8#q=order+of+argument+evaluation+in+ocaml+&*,而不是直接在SO上搜索。 - Oleg
好的,那么下次你就会知道了。 - Lhooq
显示剩余3条评论
1个回答

7
函数参数的求值顺序在OCaml中未指定。
这在手册第6.7节中有所记录。
实质上,这给了系统(编译器或解释器)以最大的自由度来以某种有利的顺序求值表达式。这意味着你(作为OCaml程序员)必须编写不依赖于求值顺序的代码。
如果你的代码是纯函数式的,那么它的行为不能依赖于顺序。因此,只有在编写带有副作用的代码时需要小心。 更新 如果你关心顺序,请使用let
let a = <expr1> in
let b = <expr2> in
f a b

或者,更一般地说:

let f = <expr0> in
let a = <expr1> in
let b = <expr2> in
f a b

更新2

值得一提的是,你引用的那本书是2002年出版的。自那时以来,很多事情都发生了变化,包括语言名称。更为现代的资源是Real World OCaml


但是Ocaml也有面向对象的一面(目前对我来说还不清楚),难道没有任何例子表明顺序很重要吗? - Oleg
1
制作示例(使用或不使用OOP子系统)以产生不同的参数评估顺序产生不同行为是一点也不困难。这类代码具有未指定的行为,因此您不应编写此类代码 :-) - Jeffrey Scofield
那么这就是我们的契约了 :)?编写代码,具有相同的确定性行为,无论参数评估的顺序如何。 - Oleg
1
是的,就是这样。如果你主要编写函数式代码,或者在表达式中没有副作用的情况下作为函数参数使用,那么这很容易。如果您关心顺序,请使用 let(请参见上文)。 - Jeffrey Scofield

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接