首页 > 解决方案 > 是否在每个函数调用上评估可选参数的默认值?

问题描述

OCaml 规范记录了对可选参数的默认值的使用,但没有指定如果默认值是例如每次可以返回不同值的函数会发生什么。

从一些测试来看,如果没有传入参数,似乎每次都会评估该值;例如

let x = ref 0;;

let incr x =
  x := !x + 1;
  !x
;;

let test ?(a = incr x) () = a;;

调用test ()导致 1、2、3,...,每次递增,但调用test ~a:123 ()不会递增 ref。

看起来像是跑步的行为,test ()或者test ~a ()大致类似于

let test ?a () =
  let a =
    match a with
    | None -> incr x
    | Some a -> a
  in
  body_of_test ~a ()
;;

这是建模的正确方法吗?而且,这种行为是否记录在某处?

标签: functionocamloptional-parameters

解决方案


这确实是预期的行为。从文档中查看(强调我的):

形式的函数fun ? lab :( pattern = expr0 ) -> expr等价于 fun ? lab : ident -> let pattern = match ident with Some ident -> ident | None -> expr0 in expr

whereident是一个新变量,除了在expr0评估时未指定。

尽管对增量的评估按照您的想法进行,但在函数应用程序中“隐藏”效果是非常不明智的。值得注意的是,以下代码可能返回truefalse不保证另一个版本的编译器会给出相同的行为。

let test2 ?(a = incr x) ?(b = incr x) () = a < b
if test2 () then ...

推荐阅读