【问题标题】:OCaml Optional ArgumentOCaml 可选参数
【发布时间】:2014-07-05 09:21:45
【问题描述】:
如何在 OCaml 中编写一个函数,其中一个或多个参数是可选的?
let foo x y z = if(x+y > z) then true else false;;
如果 foo 没有收到 z 参数,它将使用 0 作为 z。
foo 3 3 2 -> true
foo 3 3 10 -> false
foo 2 1 -> true
是否有任何 OCaml 功能可以实现这一点?
【问题讨论】:
标签:
functional-programming
ocaml
【解决方案1】:
OCaml 具有可选参数,但它比您想象的要复杂得多,因为 OCaml 函数基本上只有一个参数。在您的情况下, foo 是一个需要一个 int 并返回一个函数的函数。
如果您不使用尾随参数,通常这意味着您对将返回的函数感兴趣;这有时被称为部分应用。
结果是尾随可选参数(如您所要求的)不起作用。
可选参数总是与一个名称相关联,该名称用于判断是否提供了参数。
如果您将z 设为函数的第一个参数而不是最后一个参数,则可以得到如下结果:
# let foo ?(z = 0) x y = x + y > z;;
val foo : ?z:int -> int -> int -> bool = <fun>
# foo 3 3 ~z: 2;;
- : bool = true
# foo 3 3 ~z: 10;;
- : bool = false
# foo 2 1;;
- : bool = true
一般来说,OCaml 中的可选(和命名)参数不能解决与其他一些语言相同的问题。
我个人从不使用可选参数定义函数;因此,可能有更好的方法来实现您的要求。
【解决方案2】:
OCaml 没有 Java 或 C# 中的可选参数。由于可以部分应用函数,因此可选参数会使您很难判断何时完成传递参数并希望对函数进行评估。但是,OCaml 确实有labeled arguments with default values,可以用来达到同样的效果。
标签参数的常见警告适用。请注意,带标签的参数不能出现在参数列表的末尾,因为函数在获得所需的所有内容后就会立即进行评估:
let foo x y ?z_name:(z=0) = (x + y) > z;;
Characters 12-39:
let foo x y ?z_name:(z=0) = (x + y) > z;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Warning 16: this optional argument cannot be erased.
val foo : int -> int -> ?z_name:int -> bool = <fun>
参数列表的其他部分很好:
# let foo ?z:(z=0) x y = (x + y) > z;;
val foo : ?z:int -> int -> int -> bool = <fun>
# foo 1 1;;
- : bool = true
# foo (-1) (-1);;
- : bool = false
# foo ~z:(-42) (-1) (-1);;
- : bool = true
以与上述相同的方式,一旦在参数列表中“移过”可选参数,您将无法提供可选参数:
# foo 1;;
- : int -> bool = <fun>