Jane Street's Core lib has such a function: Fn.const
.
https://github.com/janestreet/core_kernel/blob/master/lib/fn.ml
let const c = (); fun _ -> c
val const : 'a -> 'b -> 'a
produces a function that just returns its first argument
I really don't understand it.
();
first? let const c = fun () -> c
? this will give a function taking unit
as parameter and always returns initial c
. let f = const 5
, f
will become a function which takes '_a
as parameter. What's the purpose of returning a function with weak polymorphic parameter? p.s. I see that several functions inside Fn
module all have ();
before returning a function, what is the usage of ();
?
What's the purpose of this function? In what scenario we have to use it?
You'd use it in a context where a function taking an argument is required, but you don't actually care about the argument and just want to return the same value each time. A trivial example would be List.map (const 42) xs
, which turns a list of n items into a list of n 42s.
A less silly (but more abstract) example would be a function that does something to produce a value, but under certain (say, in case the something did not succeed) conditions instead calls a user-supplied function to produce the value instead giving it some information about the situation as the argument. In some situations you might not case about the information and just return the same default value every time, so const
would work here.
Why put (); first?
In its internal representation, as well as the generated code, the OCaml compiler actually has multi-argument functions. If you define a function like let f x y = ...
or let f x = fun y -> ...
, OCaml actually turns this into a 2-argument function (rather than a 1-argument function returning another function) internally. So when you then do f 1 2
to call it, that's a simple call to a 2-argument function, which is much more efficient than the alternative. However if you just do f x
, some extra code will be generated to create the closure. This is less efficient than returning the closure directly.
So this optimization improves the performance when you call a function with all its arguments, but is actually counter-productive when you don't. Adding the ()
in front disables the optimization (because the function no longer has the form f x = fun y -> ...
). Since const
is meant to be called with just a single argument (directly calling const x y
makes no sense as you could just as well write x
), this improves the performance.
Why not write it as let const c = fun () -> c? this will give a function taking unit as parameter and always returns initial c.
Because then the function would only work in a context where a function taking unit
is expected, which would be the vast minority of cases. For example List.map (const 42) xs
would now only work if xs
is a list of units, which it's almost certainly not.
1., 2. and 3.: see seppk's answer
4.: The OCaml type system is such that functions can't return polymorphic values. Your should read Gabriel's answers about it: What is the difference between 'a and '_l? overgeneralized curried fns
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