Currying and partial application
It is extremely common to find definitions and examples of currying that actually refer to partial function application , or partial application of functions. For those who, like me, are interested in functional programming without actually mastering any purely functional language, the two concepts are usually even more confusing. I will try to explain the difference as I use it to consolidate my own understanding of the subject. All my examples use JavaScript, but I imagine they are understandable for those who use C, Java, C #, among other languages.
Partial application
In functional languages, functions are not "invoked," but "applied" to their arguments. Functions are also known as "first class citizens" of the language, that is, they can be assigned to variables, and interact with other functions that can be passed as parameters or returned.
A function is "partially applied" when it is applied to only part of the parameters it expects, and returns another function that expects the remaining parameters. So partial application is a way to get a function and fix (or, as said Zuul , "stuck") certain parameters .
For example, the following JavaScript function expects three parameters:
function soma(a, b, c) {
return a + b + c;
}
// Duas maneiras diferentes de invocar:
soma(1, 2, 3); // 6
soma.apply(null, [1, 2, 3]); // 6
Let's create a function that applies soma
partially, ie fixes the first parameter and returns a function that expects the other two:
function somap(a) {
return function(b, c) {
return soma(a, b, c)
}
}
// Uso:
var somadois = somap(2);
somadois(3, 4); // 9
This operation can be generalized to any function:
function partial(fn) {
// Guarda argumentos após fn numa array
var args = Array.prototype.slice.call(arguments, 1);
return function() {
return fn.apply(null, args.concat(Array.prototype.slice.call(arguments, 0)));
};
}
var somadois = partial(soma, 2);
somadois(3, 4); // 9
In fact, JavaScript already supports this natively with bind
that the functions have:
var somadois = soma.bind(null, 2);
Currying
The definition of currying from the Zuul's answer is accurate and succinct (emphasis added):
Currying is the name given to the technique of dividing a function that takes several arguments in a series of functions each dealing with an argument of the initial function.
Notice that our example above does not meet this definition, because partial(soma, 2)
returns a function that handles two arguments of soma
, not one. If our function did currying, we would have to call it like this to get the final result:
var somadois = curry(soma, 2);
somadois(3)(4); // 9
The practical use of this in JavaScript (among other languages) is debatable. There are examples of justified uses, but in most cases there is not much advantage. Implementations of currying functions are possible in JavaScript, but not without some limitations.
Currying is very useful in languages where functions are always unary, that is, they accept a single argument. In them, currying is just a way to implement functions that accept more than one argument. And certain languages implement functions with multiple parameters using currying internally . From this link, the following examples in OCaml are equivalent:
let foo = fun a b ->
a * a + b * b
and
let foo = fun a ->
fun b ->
a * a + b * b
In OCaml, the first way to define the function is only syntactic sugar for the second. Both produce identical function objects. And in both cases the call is equal, for example foo 1 2
- that would be foo(1)(2)
in JavaScript.
I found in Programmers an interesting point of view on this (in free translation):
For me currying is important as a theoretical construct that allows us to consider all functions as unary, since any other function can be reduced to such a function.