views:

576

answers:

5

Writing as an unreconstructed imperative & OO programmer...

Have messed about with Erlang and also Haskell lately. I like Erlang, not sure yet about Haskell. Functional seems more like math than programming, hope that makes sense. Functional programming seems very powerful.

Reading docs on the interwibble wrt functional programming I come across the word 'currying' constantly. I seem to be finding only docs that are somewhat over my head - much terminology that is not defined.

What is currying?

I have looked for similar already posted questions but did not find anything, so feel free to point me to established thread.

TIA.

+7  A: 

Currying is a way to transform functions that take multiple parameters to functions that return functions that take arguments successively. That is, to transform:

f(x, y, z)          //  (int,int,int) -> int

to

g(x)(y)(z)          //  int -> (int -> (int -> int))

in which g(x) returns another function, h(y) that takes an argument and returns j(z).

It is originated from mathematical ideas. In lambda calculus functions take a single parameter and this approach effectively enables creation of functions that take tuples.

In programming, you can use this approach to partially apply a function to some value while leaving other values undecided, and probably pass the partially applied function to another procedure to apply to actual arguments to produce return values.

Mehrdad Afshari
+10  A: 

In an algebra of functions, dealing with functions that take multiple arguments (or equivalent one argument that's an N-tuple) is somewhat inelegant -- but, as Moses Schönfinkel (and, independently, Haskell Curry) proved, it's not needed: all you need are functions that take one argument.

So how do you deal with something you'd naturally express as, say, f(x,y)? Well, you take that as equivalent to f(x)(y) -- f(x), call it g, is a function, and you apply that function to y. In other words, you only have functions that take one argument -- but some of those functions return other functions (which ALSO take one argument;-).

As usual, wikipedia has a nice summary entry about this, with many useful pointers (probably including ones regarding your favorite languages;-) as well as slightly more rigorous mathematical treatment.

Alex Martelli
I suppose similar comment to mine above - I have not seen that functional languages restrict functions to taking a single arg. Am I mistaken?
Eric M
@hoohoo: Functional languages don't generally restrict functions to a single argument. However, on a lower, more mathematical level it's a lot easier to deal with functions that only take one argument. (In lambda calculus, for example, functions only take one argument at a time.)
Sam DeFabbia-Kane
OK. Another questions then. Is the following a true statement? Lambda calculus can be used as a model of functional programming but functional programming is not necessarily applied lambda calculus.
Eric M
Alex Martelli
Eric M
A: 

I found this article, and the article it references, useful, to better understand currying: http://blogs.msdn.com/wesdyer/archive/2007/01/29/currying-and-partial-function-application.aspx

As the others mentioned, it is just a way to have a one parameter function.

This is useful in that you don't have to assume how many parameters will be passed in, so you don't need a 2 parameter, 3 parameter and 4 parameter functions.

James Black
+2  A: 

Here's a concrete example:

Suppose you have a function that calculates the gravitational force acting on an object. If you don't know the formula, you can find it here. This function takes in the three necessary parameters as arguments.

Now, being on the earth, you only want to calculate forces for objects on this planet. In a functional language, you could pass in the mass of the earth to the function and then partially evaluate it. What you'd get back is another function that takes only two arguments and calculates the gravitational force of objects on earth. This is called currying.

Shea Daniels
As a curiosity, the Prototype library for JavaScript offers a "curry" function that does pretty much exactly what you've explained here: http://www.prototypejs.org/api/function/curry
brownstone
That's pretty cool. I did this example in Scheme a long time ago...
Shea Daniels
+1  A: 

Here's a toy example in Python:

>>> from functools import partial as curry

>>> # Original function taking three parameters:
>>> def display_quote(who, subject, quote):
        print who, 'said regarding', subject + ':'
        print '"' + quote + '"'


>>> display_quote("hoohoo", "functional languages",
           "I like Erlang, not sure yet about Haskell.")
hoohoo said regarding functional languages:
"I like Erlang, not sure yet about Haskell."

>>> # Let's curry the function to get another that always quotes Alex...
>>> am_quote = curry(display_quote, "Alex Martelli")

>>> am_quote("currying", "As usual, wikipedia has a nice summary...")
Alex Martelli said regarding currying:
"As usual, wikipedia has a nice summary..."

(Just using concatenation via + to avoid distraction for non-Python programmers.)

Editing to add:

See http://docs.python.org/library/functools.html?highlight=partial#functools.partial, which also shows the partial object vs. function distinction in the way Python implements this.

Anon
I do not get this - you do this: >>> am_quote = curry(display_quote, "Alex Martelli")but then you do this next: >>> am_quote("currying", "As usual, wikipedia has a nice summary...")So you have a function with two args. It would seem that currying should give you three different funcs that you would compose?
Eric M
I am using partial to curry only one parameter, producing a function with two args. If you wanted, you could further curry am_quote to create one that only quoted Alex on a particular subject. The math backgound may be focused on ending up with functions with only one parameter - but I believe fixing any number of parameters like this is commonly (if imprecisely from a math standpoint) called currying.
Anon
(btw - the '>>>' is the prompt in the Python interactive interpreter, not part of the code.)
Anon
OK thanks for the clarification about args. I know about the Python interpreter prompt, I was trying to quote the lines but it diidn't work ;-)
Eric M
After your comment, I searched and found other references, including here on SO, to the difference between "currying" and. "partial application" in response to lots of instances of the imprecise usage I'm familiar with. See for instance: http://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application
Anon
@Anon: I just re-read your example and saw that I missed the point. The first arg to display_quote() is after currying to produce am_quote() not present in am_quote(), but the value is carried. If I decompose display_quote() by hand I can produce 3 functions that could be composed to get the same result as display_quote() without fixing the values of any args. The call am_quote = curry(display_quote, "Alex Martelli") seems to me to turn arg 1 of display_quote into a constant string. Is this part of the point of currying, or an artifact of an approach to currying?
Eric M
I think that is exactly the crux of the terminology issue. I, like numerous others out there, was using the term in a way where wiring in arguments was the whole point of currying. Others, I have learned thanks to your question ;-), would instead agree with "artifact of an approach to currying." Good to know this difference in usage exists out there.
Anon
@Anon - well it is a quite new and still somewhat strange paradigm to me, so I certainly am not ready to state a personal preference! Knowing there is a difference in usage helps in rying understand the thing.
Eric M