Labeled and optional arguments
The type and name of a function usually give you a pretty good idea of what the
arguments should be. However, for functions with many arguments (especially
arguments of the same type), it can be useful to label them. For example, you
might guess that the function String.sub
returns a substring of the given
string (and you would be correct). You could type in String.sub
to find its
type:
# String.sub;;
- : string -> int -> int -> string
But it's not clear from the type how to use it—you're forced to consult the documentation.
OCaml supports labeled arguments to functions. You can declare this kind of function using the following syntax:
# let f ~name1:arg1 ~name2:arg2 = arg1 + arg2;;
val f : name1:int -> name2:int -> int = <fun>
This function can be called by passing the labeled arguments in either order:
f ~name2:3 ~name1:4;;
Labels for arguments are often the same as the variable names for them. OCaml provides a shorthand for this case. The following are equivalent:
let f ~name1:name1 ~name2:name2 = name1+name2
let f ~name1 ~name2 = name1 + name2
Use of labeled arguments is largely a matter of taste. They convey extra information, but they can also add clutter to types.
The syntax to write both a labeled argument and an explicit type annotation for it is:
let f ~name1:(arg1:int) ~name2:(arg2:int) = arg1 + arg2
It is also possible to make some arguments optional. When called without an optional argument, a default value will be provided. To declare such a function, use the following syntax:
# let f ?name:(arg1=8) arg2 = arg1 + arg2;;
val f : ?name:int -> int -> int = <fun>
You can then call a function with or without the argument:
# f ~name:2 7;;
- : int = 9
# f 7;;
- : int = 15