What's Currying in Computer Science?

, , …,

This page give several examples of function returning a function in {Mathematica, Emacs Lisp, Perl, JavaScript}, and discuss how they are different from the concept of “currying” in computer science, as features of Haskell and Ocaml, and the merits of the jargon “currying” with respect to terminology.

Quote from Jon Harrop's book 〔Ocaml for Scientist By Jon Harrop. @ http://www.ffconsultancy.com/products/ocaml_for_scientists/chapter1.html

ocaml for scientist Jon Harrop on currying
Jon Harrop on Currying

A curried function is a function which returns a function as its result.

That is incorrect.

Decomposed Function Form in {Mathematica, Emacs Lisp, Perl, JavaScript}

Here are some examples of a function that returns a function as result, but is not currying.

Mathematica:

f[n_]:=Function[n^#];
f[7][2]
(* returns 49 *)

Emacs lisp:

(defmacro f (n) (list 'lambda (list 'x) (list 'expt n 'x) ) )
(funcall (f 7) 2) ; 49

Perl:

sub f {$n=$_[0]; sub { $n ** $_[0]} };
print &{ f(7) } (2);            # 49

JavaScript 〔☛ Functional Programing in JavaScript〕:

function f(n) {return function (x) {return Math.pow(n,x);}; }
console.log(f(7) (2));          // 49

In the above, a function returns a function, and the result function is applied to a value. They demonstrate 2 features of a computer language:

These, are 2 of the features that are part of often sloppily called “function as first class citizens”.

However, the above are not languages that support currying, which is a feature of Haskell and Ocaml.

Currying is a Technique in Compiler Science

Wikipedia Currying, it defines currying this way:

In mathematics and computer science, currying is the technique of transforming a function that takes multiple arguments (or an n-tuple of arguments) in such a way that it can be called as a chain of functions each with a single argument (partial application).

Note how it says “is the technique of …”. The are 2 contexts here:

To be more concrete, in the context of a given computer language, to say that it support currying, is to mean that the compiler understands the concept to certain degree. More to the point, the language is inherently able to take a function of more than one arg and deconstruct it to several functions of single arg.

Mathematically, currying is the concept of deconstructing a function of multiple parameters to a composition of several functions all of arity 1.

Currying = Bad Jargon

Dr Jon D Harrop wrote in comp.lang.lisp (; Source groups.google.com):

It is probably worth noting that currying is comparatively uncommon in
both Lisp and Mathematica. The difference between the syntaxes is
fairly small:

  ((f a) b)  Lisp
  f[a][b]    Mathematica
  f a b      ML 

The term “currying” smacks of academic mumbo-jumbo. The primary fuel of its use among programers, is its obscurity. It makes the users of the term looks bigger then than they are. (not accusing you in anyway though).

As you know, there's the concept of turning a function with multiple parameters into a function with fewer parameters. This concept as a theory, and in particular as a actual implementation of it in a computer language as a feature, needs a name. And, the term “currying” has been adopted. (the particular reason for the word, as we know, is from the mathematician Haskell Curry).

If we were to make a general judgement on the naming of scientific/technical concepts (as a criticism about terminology), then, terms based on people's names are not to be preferred. (primarily because it imparts no information about what it means, secondarily because often it has nothing to do with the person (i.e. the named is often not the primary contributor of the theory/concept although in many cases it is meant to be and is)) Further, the quality of terminology has critical consequence, in education, efficiency of communication, and in how something is perceived.

(Richard Stallman has popularly made this point clear for non-scientific terms, mostly regarding Linux and his ideology about software in society (⁖ {GNU/Linux, Intellectual Property, Content Management System (Website Revision System), digital right management (digital restrictions management), …}. (however, himself, in my opinion, have hijacked terms intentionally or unintentionally for his gain (⁖ Free, Hacker. See: Richard Stallman's Abuse of the Word “Freedom”.))))

Currying ≠ Applying a Function Value

The term Currying is often used by high-powered Tech Geekers (such as the lispers and functional programers) to simply mean applying a function that is returned by a function, and this subtle but different meaning, generates confusion. For example, in the following:

((f a) b)  Lisp
f[a][b]    Mathematica
f a b      ML

Are they Currying? or are they just applying a return value of a function?

The significance of the term “currying”, usually lies in the context of language design. In particular, the feature of language being able to decomposing a function into one or more functions each with fewer parameters.

So, in Mathematica, form like this f[a][b] isn't currying in anyway, since the language does not have the notion of decomposing a function into functions with less arity. f[a][b] here is simply applying the value of f[a] to b.

Similarly, ((f a) b) in lisp isn't currying in anyway.

Manually Defining a Function with Currying Property in Mathematica

In Mathematica, forms like f[a][b] or f[a1,a2,…][b1,b2,…]… are actually used often. As a example of a buildin function, most notable one is the function named “Derivative”. It is a idiom, and is used in just about every sufficiently large body of code, and described in just about all Mathematica programing text books.

In math, often a function has a subscript to indicate its particular family, level, class, or type. For example, Derivative[n] returns a function that returns the nth derivative of its argument. (So, it can be used like this: (Derivative[n])[f] or simply Derivative[n][f], to mean the nth derivative of f.)

Such a form can be defined using pattern matching, for example:

f[a_][b_] := a+b

If you call f[x], it is meaningless, because the pattern doesn't match.

However, often, in such a form, the programer (or mathematicians using the language) considers f to be a family function. When given a index, it returns a specific function of that family. (⁖ Derivative is a family of function. Derivative[n] returns a specific one.) So, they want f[x] to return function. In this case, f can be defined using pattern matching, or not using pattern matching. Example:

(*using pattern matching*)
f[x_] := a+x;
f[a_][b_] := a+b
(*without using pattern matching. Explicit/Manual definition of currying here for f. *)
f = Function[a, Function[b, a+b]]

Calling f[a] now makes sense. In the first case, it returns a + x, for whatever value a at run time (if no value, it remains in symbolic form). In the non-pattern-matching example, it returns a proper function, which then can be applied to a value. If f[a][b] is called, it evaluates to a+b.

Now, we have currying. Note that we MANUALLY, EXPLICITLY, defined “currying” for a specific function f of a specific arity of 2, in Mathematica. (this can be done in any language that supports returning a function as value and applying such to a value. ⁖ JavaScript, perl, python.)

In the over one thousand pages of the Mathematica Book (its official manual), covering hundreds of advanced math functions and computations, one will find no mentioning of Currying or its concept whatsoever. (and this is in supreme contrast to the common programer and academics obfuscation and elitism of throwing out lambdas, currying, liiinda-meryer types, garbage collection, tail-recursion, and other shit. 〔☛ The Idiocy of Computer Language Docs〕 )

A Better Jargon for Currying

What'd be a better jargon for currying?

blog comments powered by Disqus