(Chapter written by Jacques Garrigue)
This chapter gives an overview of the new features in
Objective Caml 3: labels, and polymorphic variants.
If you have a look at modules ending in Labels in the standard
library, you will see that function types have annotations you did not
have in the functions you defined yourself.
#ListLabels.map;;
- : f:('a -> 'b) -> 'a list -> 'b list = <fun>
#StringLabels.sub;;
- : string -> pos:int -> len:int -> string = <fun>
Such annotations of the form name: are called labels. They are
meant to document the code, allow more checking, and give more
flexibility to function application.
You can give such names to arguments in your programs, by prefixing them
with a tilde ~.
#let f ~x ~y = x - y;;
val f : x:int -> y:int -> int = <fun>
#let x = 3 and y = 2 in f ~x ~y;;
- : int = 1
When you want to use distinct names for the variable and the label
appearing in the type, you can use a naming label of the form
~name:. This also applies when the argument is not a variable.
#let f ~x:x1 ~y:y1 = x1 - y1;;
val f : x:int -> y:int -> int = <fun>
#f ~x:3 ~y:2;;
- : int = 1
Labels obey the same rules as other identifiers in Caml, that is you
cannot use a reserved keyword (like in or to) as label.
Formal parameters and arguments are matched according to their
respective labels1, the absence of label
being interpreted as the empty label.
This allows commuting arguments in applications. One can also
partially apply a function on any argument, creating a new function of
the remaining parameters.
#let f ~x ~y = x - y;;
val f : x:int -> y:int -> int = <fun>
#f ~y:2 ~x:3;;
- : int = 1
#ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
#ListLabels.fold_left [1;2;3] ~init:0 ~f:(+);;
- : int = 6
#ListLabels.fold_left ~init:0;;
- : f:(int -> 'a -> int) -> 'a list