OCaml 是否支持按名称传递参数?

Does OCaml support call-by-name parameter passing?

Scala 允许使用“=>”语法按名称调用 函数参数。例如,布尔 and 函数可以定义为:

def and(x: Boolean, y: => Boolean): Boolean =
  if (x) y else false

第二个参数是call-by-name。这确保了预期的“短路”行为——如果 xfalse,则根本不会评估 y

一般来说,这对于可能根本不使用参数的函数很有用。

如何在 OCaml 中完成此操作?

我知道 OCaml 有惰性求值的结构,但我不清楚这些是否以及如何用于按名称调用的参数传递。

首先,通过构造,布尔运算符是惰性的:

# false || (print_endline "second"; true);;
second
- : bool = true
# true || (print_endline "second"; true);;
- : bool = true
# true && (print_endline "second"; false);;
second
- : bool = false
# false && (print_endline "second"; false);;
- : bool = false

然后,对于更多的自定义函数,你确实应该使用惰性(惰性值在计算后被记忆的巨大好处):

let fib n =
  let rec aux n b a =
    Printf.printf "%d %d %d\n" n b a;
    if n <= 0 then a else aux (n - 1) (a + b) b
  in
  aux n 1 0

let f a b = if b > 0 then Lazy.force a + 1 else b
(* val f : int lazy_t -> int -> int = <fun> *)

let () =
  let r = lazy (fib 10) in
  let r2 = lazy (fib 1000000) in
  Printf.printf "%d\n" (f r 1 + f r 2 + f r2 0)

结果将是:

10 1 0
9 1 1
8 2 1
7 3 2
6 5 3
5 8 5
4 13 8
3 21 13
2 34 21
1 55 34
0 89 55
112

r 只计算过一次,r2 从未计算过。