OCaml spec记录了默认值在可选参数中的使用,但是没有指定默认值例如是每次可能返回不同值的函数。
经过一些测试,似乎每次if都没有传入参数时,都会对值进行求值;例如
let x = ref 0;;
let incr x =
x := !x + 1;
!x
;;
let test ?(a = incr x) () = a;;
调用test ()
会导致1、2、3,...,每次递增,但是调用test ~a:123 ()
不会使引用递增。
似乎运行test ()
或test ~a ()
的行为大致类似于
let test ?a () =
let a =
match a with
| None -> incr x
| Some a -> a
in
body_of_test ~a ()
;;
这是建模的正确方法吗?而且,此行为是否记录在某处?
这确实是预期的行为。从documentation(强调我的)中查看:
fun ? lab :( pattern = expr0 ) -> expr
形式的函数等效于fun ? lab : ident -> let pattern = match ident with Some ident -> ident | None -> expr0 in expr
其中
ident
是一个新鲜变量,除了在评估expr0
时未指定,否则除外。
尽管对增量的求值方法如您所愿,但在功能应用程序中“隐藏”效果是极不明智的。值得注意的是,下面的代码可能返回true
或false
,但不能保证编译器的另一个版本会产生相同的行为。
let test2 ?(a = incr x) ?(b = incr x) () = a < b
if test2 () then ...