What is it and what are the advantages of Currying?

Asked

Viewed 1,375 times

22

This is a very widespread concept in functional languages, but what it is exactly?

Why is it advantageous?

Bonus point: Is it possible to use it in non-functional languages? Or more generally, in languages that do not have specific facilities? Can you give some example? And the same advantages would apply?

2 answers

19


Currying and partial application

It’s 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, usually the two concepts become even more confused. I will try to explain the difference while I take the opportunity to consolidate my own understanding of the subject. All my examples use Javascript, but I imagine they are understandable to 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, i.e., can be assigned to variables, and interact with other functions 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 take a function and fix (or, like said the Zuul, "enter") certain parameters.

For example, the following function in Javascript 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, that is, sets 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 method bind that the functions have:

var somadois = soma.bind(null, 2);

Currying

The Currying Definition of zuul’s response is accurate and succinct (my griffin):

Currying is the name given to the technique of dividing a function that takes several arguments into a series of functions each dealing with one argument from the initial function.

Note that our example above does not meet this definition because partial(soma, 2) returns a function that deals with two arguments of soma, and not one. If our function did currying, we would have to call it so to get the final result:

var somadois = curry(soma, 2);
somadois(3)(4); // 9

The practical usefulness 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 sane possible in Javascript, but not without some limitations.

Currying is very useful in languages where functions are always unary, i.e., accept a single argument. In them, currying is just one way to implement functions that accept more than one argument. And certain languages implement multi-parameter functions 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) javascript.

I found in the Programmers an interesting point of view on this (in free translation):

For me the currying is important as a theoretical construct that allows to consider all functions as unary, since any other function can be reduced to such a function.

16

Currying (English) is the name given to the technique of dividing a function that takes several arguments into a series of functions each dealing with an argument from the initial function.

Of mathematical origins, created by Moses Schönfinkel and later perfected by Haskell Curry.

After applying the technique of Currying a function accepts the first argument of the original function by returning a function that accepts the second argument of the original function and so on until all arguments are being worked by individual functions.

In practical terms, the advantage of Currying is that we have, especially in large projects, functions that are called multiple times with one or more parameters of equal value between them. With the technique of Currying the repetition of code and/or values in the parameters is avoided.

Practical Example

See on Jsfiddle

The Javascript framework Prototype (English) has an implementation of Curry (English) which allows you to "insert" parameters into the original function and then pass an infinite number of additional parameters.

The practical example they present in the documentation demonstrates well the use and advantage of Currying:

// Função de exemplo para fazer "alert" do argumentos
function showArguments() {
  alert($A(arguments).join(', '));
}

// Vai gerar um "alert" de três argumentos "1, 2, 3"
showArguments(1, 2, 3);

/* "cravar" três argumentos em f e passar mais dois, resultando numa função
 * com 5 argumentos 3 dos quais comuns a outras funções
 * alerta "1, 2, 3, a, b"
 */
var f = showArguments.curry(1, 2, 3);
f('a', 'b');

Having f with 3 arguments Curry, we can call it again without having to repeat them, thus saving the said repetition of code and arguments:

// alerta "1, 2, 3, c, d"
f('c', 'd');

Learn more

More can be read on this subject not only in the links already provided but also in the answers given to these questions in the SOEN:

Browser other questions tagged

You are not signed in. Login or sign up in order to post.