Domanda

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.

  1. What's the purpose of this function? In what scenario we have to use it?
  2. Why put (); first?
  3. Why not write it as let const c = fun () -> c? this will give a function taking unit as parameter and always returns initial c.
  4. If I do 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 ();?

È stato utile?

Soluzione

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.

Altri suggerimenti

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top