OCaml& amp;中的功能应用列表OCaml评估模型

时间:2018-02-28 16:48:15

标签: functional-programming ocaml

我对OCaml的评估模型不太熟悉。如果有人能解释为什么这两行代码会产生不同的结果,我将不胜感激:

List.iter (fun s -> Printf.printf "%s" s) ["a"; "b"; "c"];; (* prints abc *)

List.iter (fun f -> f) [Printf.printf "a"; Printf.printf "b"; Printf.printf "c"];; (* prints cba *)

2 个答案:

答案 0 :(得分:4)

OCaml是一种严格的函数式编程语言:函数的参数在传递给函数之前被评估为值(并且表达式中的副作用发生)(并且函数内部的任何副作用都可能发生)。

为了理解你的第二个例子,最好稍微去掉它: List.cons (Printf.printf "a") (List.cons (Printf.printf "b") (List.cons (Printf.printf "c") []))

当一个函数同时传递多个参数时 - 就像这里所有List.cons函数的情况一样 - 参数的评估顺序是未指定的。例如,字节码和本机编译器之间的顺序可能不同。在这里,您使用的编译器决定首先评估第一个List.cons的第二个参数。在这样做时,它遇到了一个应用程序(第二个List.cons

...

在评估上一个List.cons的参数时,它打印了c。结果是(),这允许它构建值[()]。这个论点准备好了,它现在评估了第二个List.cons的另一个参数。这使它打印b。最后,由于第一个[();()]的参数List.cons已准备就绪,因此它评估了另一个参数。这使它打印a

答案 1 :(得分:1)

正如Pascal Cuoq已经回答了你的问题,让我澄清一下我从问题标题中可能产生的误解:你的代码中没有任何一个功能列表。

在第一行中有一个字符串列表["a";"b";"c"]

在第二行中,您有一个包含Printf.printf "a"等元素的列表,这些元素是函数应用程序。它们的结果类型是unit,也不是函数类型。 (事实上​​,列表只是[();();()]。)

功能列表的一个例子是

[(fun () -> print_string "a"); (fun () -> print_string "b"); (fun () -> ())]