It's really just called currying, but that's not a
WikiName. Currying is a property of functions discovered by Moses Schoenfinkel in 1924. However at the time,
HaskellCurry got most of the good press about
FunctionalProgramming so it was named after him. The term itself was supposedly invented by
ChristopherStrachey.
If you read the FAQ, you'll see that the property described (the isomorphism of AxB->C with A->B->C) was a "well known fact" well before Schoenfinkel and Curry. Their contributions were apparently in the area of the EssAndKayCombinators.
Currying is the concept that functions of multiple arguments are really just
HigherOrderFunctions which take one argument and return functions. In a sort of Javaish syntax, Here are examples:
// two arg version
int sum(int a, int b) { return (a+b); }
// one arg version
int sum(int a) { return int sum1(int b) { return (a+b); } }
// optimised multiplication
int mult(int a, int b) {
select (a) {
case -1: return int neg(int b) { return -b; }
case 0: return int zero(int b) { return 0; }
case 1: return int ident(int b){ return b; }
default: return int std(int b) { return a*b; }
}
}
In fact you could write that in
legitimate JavaScript:
// two arg version
var sum = function(a, b) { return (a+b); }
// one arg version
var sum = function(a) { return function(b) { return (a+b); }}
// Which would be used as, e.g.,
var plusfour = sum(4);
var six = plusfour(2);
var alsosix = sum(4)(2);
// optimised multiplication
function mult(a) {
switch(a)
{
case -1: return function(b) { return -b; }
case 0: return function(b) { return 0; }
case 1: return function(b) { return b; }
default: return function(b) { return a*b; }
}
}
var answer = mult(6)(9);
"And why would I care?" <-- That's what I was thinking when I read this. ;->
But now I see an application of this:
This idea is used quite heavily in the
SynthesisOs. You see, if the value of "a" is known at one point in the run, and we intend to add lots of "b" values to it, then
SynthesisOs calls "sum(int a)", which generates the code to do "sum1(int b)" -- where 'a' is a constant. This is called
PartialEvaluation. It gives
SynthesisOs a
substantial performance boost, as it can do code optimization based on the value of 'a'. Like, if 'a' happens to be zero, it generates/returns the code "int sum1(int b) { return b; }", optimizing the addition right out. Likewise, if 'a' is one, it generates/returns the function "int sum1(int b) { return ++b; }". Fast. Very fast. (See the paper on
SynthesisOs. It claims "10 times faster than Unix.") --
JeffGrigg
"And why would I care?"
Because it makes programming much easier and programs much easier to understand. For example, here's a piece of Haskell code to double all elements of a list:
double aList = map (* 2) aList
That is, to double a list, apply "* 2" to each element -- the * operator has been curried.
And this definition can itself be curried, so that:
double = map (* 2)
--
NatPryce
Is that really that much easier to understand than
@alist = map {$_ * 2} @alist;
...But that code does not define a new function.
But it does define a PerlLanguage block, which, if I understand correctly, is a code object with a lot of the same properties as a scheme closure.
(No, it doesn't; it defines an array, "@alist".
But it does so in terms of the block '{$_ * 2}', which is in effect an anonymous function)
To elaborate:
double = map (* 2)
list1 = [1, 2, 3, 4, 5]
list2 = [10, 20, 30, 40, 50]
double list1
>[2, 4, 6, 8, 10]
double list2
>[20, 40, 60, 80, 100]
In the
FortranLanguage this particular (and many similar problems) can be reduced to
A = A * 2
where A is a arbitrarily shaped array. But that is not the point.
You can curry objects too.
For example, instead of sending
window drawCircleAt: 10@10 Colour: #red
window drawCircleAt: 20@20 Colour: #red
window drawCircleAt: 30@30 Colour: #red
you can curry away the Colour argument, making a new object called a pen.
pen := window pen colour: #red
pen drawCircleAt: 10@10
pen drawCircleAt: 20@20
pen drawCircleAt: 30@30
CurriedObject is a generalisation of a number of other patterns, like
AbstractSession,
IteratorPattern, as well as pens in graphics systems.
--
JamesNoble
Given historical precedent, AbstractSession, IteratorPattern, and graphics system pens are more like specialisations of, or at least attempts to emulate aspects of, curried objects.
Other patterns seem to be trying to hark back to currying; for example, is
VisitorPattern much more than curried traversal?
I sometimes get the feeling that one of the things that has been forgotten (or at least, was
forgotten: there seems to be some attempt to recapture the idea in recent times) by the designers of OO languages is that functions are objects, too. A lot of DesignPatterns - VisitorPattern, StrategyPattern, DecoratorPattern, AdapterPattern, ... - seem like techniques for transporting functions from one object to another. Currying recognises that functions can be constructed in a series of steps.
Thank you. There is quite a lot of information on this wiki about this. One starting point is the work of
ThomasKuehne in
FunctionalPatternSystemForObjectOrientedDesign. There is also the work FC++ (
FunctoidsInCpp), an attempt to implement in
CeePlusPlus a lot of things found in
HaskellLanguage. --
JohnFletcher
CategoryFunctionalProgramming