Reputation: 1481
Suppose a function bind
has a labelled argument, optional arguments and unlabelled arguments, and you want to define a method m
that applies the unlabelled arguments of bind
and returns the partially applied function, so that the user of m
can apply the labelled or optional arguments of bind
. How do you do this? Simply writing method m = bind a b [...] z
causes the compiler to think that the optional arguments are omitted.
Upvotes: 5
Views: 1485
Reputation: 31459
The position of the optional arguments (in the function declaration or function type) is important: they are only applied implicitly when the next non-optional argument is applied.
If you want the partial application of one parameter p
to not apply an optional parameter ?o
, put ?o
after p
in the function declaration.
Contrast
# let f ?o p ~z = ();;
val f : ?o:'a -> 'b -> z:'c -> unit = <fun>
# f 1;;
- : z:'_a -> unit = <fun> (* ?o applied *)
with:
# let f p ?o ~z = ();;
val f : 'a -> ?o:'b -> z:'c -> unit = <fun>
# f 1;;
- : ?o:'_a -> z:'_b -> unit = <fun> (* ?o not applied *)
If you don't want to change the definition order, or want to partially apply all non-optional parameters, you need to explicitly capture the optional parameters that would be implicitly passed:
# (fun ?o () -> f ?o 1 ~z:2);;
- : ?o:'a -> unit -> unit = <fun>
In case you weren't familiar with it, the ?o
syntax at call site is
very handy for this: it takes an 'a option
and does the right thing to
transparently pass an optional argument, whether applied or not, to the
callee.
I have added a last ()
parameter to preserve the property that there
is at least one non-optional argument after the optional ones. It is possible to not do this, but it gets tricky and is not advised.
Upvotes: 11