How can I write a function in OCaml in which one or more argument are optional?
let foo x y z = if(x+y > z) then true else false;;
If foo do not receive the z
argument it uses 0
as z
.
foo 3 3 2 -> true
foo 3 3 10 -> false
foo 2 1 -> true
Is there any OCaml feature to achieve this?
OCaml has optional arguments, but it's quite a bit trickier than you would expect because OCaml functions fundamentally have exactly one argument. In your case, foo is a function that expects an int and returns a function.
If you leave off trailing arguments, normally this means that you're interested in the function that will be returned; this is sometimes called partial application.
The result is that trailing optional arguments (as you are asking for) do not work.
Optional arguments are always associated with a name, which is used to tell whether the argument is being supplied or not.
If you make z
the first argument of your function rather than the last, you can get something like the following:
# 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
In general I'd say that optional (and named) arguments in OCaml don't solve the same problems as in some other languages.
I personally never define functions with optional arguments; so, there may be better ways to achieve what you're asking for.
OCaml doesn't have optional arguments like you'd find in Java or C#. Since functions can be partially applied, optional arguments can make it hard to tell when you're done passing arguments and would like the function to be evaluated. However, OCaml does have labeled arguments with default values, which can be used to the same effect.
The usual caveats of labeled arguments apply. Note that labeled arguments can't appear at the end of the argument list since the function is evaluated as soon as it has everything it needs:
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>
Other parts of the argument list are fine:
# 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
In the same fashion as above, you lose the ability to supply the optional argument once you 'move past' it in the argument list:
# foo 1;;
- : int -> bool = <fun>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With