为什么我的“map”处理元素的实现顺序相反?

Flu*_*lux 4 ocaml

这是我的实现map

let rec map f lst =
    match lst with
    | [] -> []
    | hd :: tl -> f hd :: map f tl
Run Code Online (Sandbox Code Playgroud)

我尝试像这样运行它:

(* Print the given int, then return the given int. *)
let print_id n =
    print_int n;
    print_newline ();
    n

let () = ignore (map print_id [1; 2; 3])
Run Code Online (Sandbox Code Playgroud)

虽然map print_id [1; 2; 3]返回[1; 2; 3],但上面的代码打印:

3
2
1
Run Code Online (Sandbox Code Playgroud)

看来列表正在以相反的顺序处理!怎么了?

Jef*_*eld 8

OCaml 不保证表达式求值的顺序。所以这个表达式:

f hd :: map f tl
Run Code Online (Sandbox Code Playgroud)

允许map在调用 to 之前评估对 的调用f

您可以使用以下let方式来保证评估订单:

let x = f hd in
x :: map f tl
Run Code Online (Sandbox Code Playgroud)

  • 补充 Jeffrey 的答案:在实践中,当今的 OCaml 在大多数情况下实现了从右到左的评估顺序(不确定是否有反例),但当然不能保证这一点。在不久的将来,当“尾递归模构造函数”进入语言时([它刚刚被合并!](https://github.com/ocaml/ocaml/pull/9760)),这个的评估顺序具体示例可能会变成从左到右——尽管您必须显式启用优化。 (2认同)