[erlang-questions] Automatic currying

Richard A. O'Keefe ok@REDACTED
Mon May 4 06:47:56 CEST 2015


The advantage of the proposed currying function is that
it is just library code.

Let me show you what Eiffel does these days.

<Eiffel fun> ::= 'agent' [<agent receiver> '.' ]<feature name>
                 ['(' <agent argument> {',' <agent argument>}* ')']

That is, an "agent expression" looks pretty much like a normal
method call with the keyword 'agent' in front of it.

If there is no agent receiver, the Current object is the
receiver.

<agent receiver> ::= <primary> | '{' <class name> '}'.

In the first case, a call of the agent will use the
specified object; in the second case, the receiver will
be a (the first) parameter of the agent and {C} gives its
type.

<agent parameter> ::= <expression> | '?' | '{' <class name> '}'

Agent parameters that are expressions are evaluated at the
time the agent expression is evaluated.  Their values are
remembered as part of the closure.  Agent parameters that
are question marks are parameters of the agent.  The
compiler can figure out the type of such parameters, but if
you want to make it clear to humans reading the code, you
can use the {C} format if you want to.

So given a method foo of three arguments, you can write

  agent r.foo(x, y, z)          -- 0 arguments
  agent r.foo(x, y, ?)          -- \
  agent r.foo(x, ?, z)          -- these four have
  agent r.foo(?, y, z)          -- 1 argument
  agent {C}.foo(x, y, z)        -- /
  agent r.foo(x, ?, ?)
  agent r.foo(?, y, ?)
  agent r.foo(?, ?, z)
  agent {C}.foo(x, y, ?)
  ....
  agent r.foo(?, ?, ?)          -- 3 arguments
  agent {C}.foo(?, ?, ?)        -- 4
  
You can't *re-order* arguments, but you can leave any
arguments you want open, not just trailing ones, as
currying does.

Could this syntax be adapted to Erlang?
Sure.  'agent' -> 'fun', receiver -> module, '.' -> ':'.
fun f(X, ?) and fun f(?, Y) would make perfect sense,
and fun f(X, Y) would be clearly distinct from f(X, Y)
just as agent r.f(x, y) is a parameterless procedure
different from f(x, y) in Eiffel.

Currying fits nicely into languages where every function
has EXACTLY ONE argument, like ML, Miranda, F#, Clean, ...
Erlang is not such a language, and neither is Eiffel,
which is why if we *did* want a currying construct for
Erlang, Eiffel's agent expressions might be a better fit.

For what it's worth, I've got some 'currying' methods
in my Smalltalk, so that
(aBlock bindFirst: x) value: y
=
aBlock value: x value: y.
Having written them, I've found them remarkably useless.




More information about the erlang-questions mailing list