

Functional JavaScript, Part 4: Function Currying - lrichardson
http://tech.pro/tutorial/2011/functional-javascript-part-4-function-currying

======
chriswarbo
Interesting, especially aside about partial application ("holes") which I've
not seen done in JS before.

I've been using my own JS currying implementation in a few projects[1], which
pretty much matches the implementation in the article: count the function's
parameter number and build up argument lists in closures until we have enough
to call the function, then pass them all in.

However, when I was implementing the same thing in PHP[2] I discovered a nice
alteration we can make: instead of passing _all_ arguments to the curried
function, we should only pass the minimum number. If we have any left over, we
should pass them to the _return value_. This lets us chain even more things
together[3]. For example:

    
    
        // "c" is our currying function
        var id     = c(function(x)       { return x;         });
        var triple = c(function(x, y, z) { return x + y + z; });
    
        // These work with both currying functions
        id(triple)('Hell', 'o Wor', 'ld');
        id(triple)('Hell')('o Wor', 'ld');
        id(triple)('Hell', 'o Wor')('ld');
        id(triple)('Hell')('o Wor')('ld');
    
        // These only work with the altered version
        id(triple, 'Hell', 'o Wor', 'ld');
        id(triple, 'Hell')('o Wor', 'ld');
        id(triple, 'Hell', 'o Wor')('ld');
        id(triple, 'Hell')('o Wor')('ld');
    

[1]
[http://chriswarbo.net/index.php?page=news&type=view&id=curry...](http://chriswarbo.net/index.php?page=news&type=view&id=currying-
in-javascript)

[2]
[http://chriswarbo.net/index.php?page=news&type=view&id=admin...](http://chriswarbo.net/index.php?page=news&type=view&id=admin-
s-blog%2Fpartial-application)

[3]
[http://chriswarbo.net/index.php?page=news&type=view&id=admin...](http://chriswarbo.net/index.php?page=news&type=view&id=admin-
s-blog%2Fbetter-currying-in)

~~~
lrichardson
This is very interesting. I'm not so sure this wouldn't trip me up some times
though. What if the first argument you are expecting, is supposed to be a
function? I would think that would be a pretty common scenario...

Unless I'm not quite getting what you mean?

EDIT: I see that this would only happen if you passed in more arguments than
expected, thus it wouldn't be a problem.

Very cool! I might update mine to work this way.

~~~
chriswarbo
Indeed, the behaviour should be identical when too few or exactly enough
arguments are given.

The way I see it, if we're not given enough arguments we introduce wrappers
around our function to accept the rest. With this alteration, when we're given
too many arguments we eliminate wrappers from around our result by passing
them the rest.

This hints that they might be 'dual' notions, in a Mathematical sense. Maybe I
should dub it "cocurrying"? ;)

~~~
chriswarbo
> This hints that they might be 'dual' notions, in a Mathematical sense. Maybe
> I should dub it "cocurrying"?

After a little more thought I've realised that this is exactly uncurrying of
return values.

When we uncurry, we take a bunch of arguments at once and supply them one-at-
a-time to our function, for example "uncurry(foo)(a, b, c, d)" becomes
"foo(a)(b)(c)(d)".

Note that this is identical to the calling convention of a curried function,
hence the name uncurrying. In this way, it makes sense to uncurry the return
value of curry:

    
    
        // Pass 3 values to a curried function which just-so-happens to return
        // other functions
        curry(function(w, x) {
          return function(y) {
            return function(z) {
              return w + x + y + z;
            };
          };
        })(1, 2, 3, 4);
    
        // Take the first 2 arguments to be w and x
        (function(w, x) {
          return function(y) {
            return function(z) {
              return w + x + y + z;
            };
          };
        })(1, 2)(3, 4);
    
        // Apply the first function
        (function(y) {
          return function(z) {
            return 1 + 2 + y + z;
          };
        })(3, 4);
    
        // The above version will ignore 4 and wait for another z.
        // This is why we need to uncurry it.
        uncurry(function(y) {
          return function(z) {
            return 1 + 2 + y + z;
          };
        })(3, 4);
    
        // Now we can execute it properly
        (function(y) {
          return function(z) {
            return 1 + 2 + y + z;
          };
        })(3)(4);
    
        (function(z) {
          return 1 + 2 + 3 + z;
        })(4);
    
        10;
    

Now, given our implementations of curry, we don't actually have to uncurry a
function explicitly: we can call "foo(a, b, c, d)" even if "foo" is curried.
Hence we can just pass all the arguments straight into the return value
_assuming that_ it is uncurried.

This will work for regular Javascript functions and those which we've curried.
The only thing it won't work for is functions which have been hard-coded in a
curried form; these will need to be sent through an uncurry function first
(which we can do via composition).

------
platz
Seems to me that using the functional style it's really important to document
the types (done in the article with the //\+ lines).

Otherwise it will be hard to make the types line up.

Also there are functions in javascript which do different things depending on
what the type of the argument is (or do different things depending on how many
arguments are passed in; those kinds of functions always have irked me), so it
would be hard to document exactly what the "type" of those functions are.

~~~
lrichardson
@platz, yes, this is correct. When currying and/or composing functions, it
becomes more difficult to determine the input/output types of the function
since the function signature won't be right there. I'm borrowing the `//+`
syntax from Brian Lansdorf, since I saw him use it and quite like it. He
mentioned he has "a lot to say on the topic" of commenting / type sigs, but I
haven't heard him speak specifically on that.

Also, for functions that do different things depending on how many arguments
are passed in, you would _never_ want to curry these. The curry function
relies on the function passed in expecting a specific number of arguments.

~~~
platz
Part of me thinks that if you're going to pursue this style to it's extreme,
you might as well just be better off using something like purescript

[http://purescript.readthedocs.org/en/latest/intro.html#hello...](http://purescript.readthedocs.org/en/latest/intro.html#hello-
purescript)

~~~
lrichardson
I haven't had a chance to try purescript yet, but I have looked at it. Really
though, I love JavaScript, and don't have much desire to use another language
that that transpiles into it...

~~~
platz
Fair enough, there's always headaches with transpilers; I for one have been
suspicious of all the coffeescript+derivatives.

------
ceedan
"In most web applications the "bottle-neck" is going to be DOM interaction. It
is very unlikely that you will notice a performance hit at all."

uhhh, 2 wrongs don't make it right?

"It is very unlikely that you will notice a performance hit at all."

Until you do..

\--

I could never justify using this stuff at work. It's inefficient, unfamiliar
to most JS developers and even if it did pass a peer review, nobody else would
actually want to maintain it.

~~~
chriswarbo
> I could never justify using this stuff at work. It's ... unfamiliar to most
> JS developers and even if it did pass a peer review, nobody else would
> actually want to maintain it.

The same could be said for any API.

Currying is actually very unobtrusive; the only time a curried function
behaves differently to its uncurried counterpart is when it's given a 'wrong'
number of arguments. The benefit is never having to perform manual eta-
expansion (ie. any time we write a redundant wrapper like "function(x) {
return bar(a, b, c, x); }").

As for efficiency, I default to having the machines doing things to save
developer's time and only do things the other way around when it's untenable
(or for fun).

------
taylodl
Another motivation for currying in JS is to memoize the curried function which
I describe in my post [http://taylodl.wordpress.com/2013/11/05/functional-
javascrip...](http://taylodl.wordpress.com/2013/11/05/functional-javascript-
currying/)

I never provided a currying function, thinking there were so many
implementations easily available - but I've never seen one as good as what's
presented here!

------
ripter
Awesome job! I was trying to understand curry by learning Haskell but you
summed it up perfectly.

What is the difference between curry and partial? Is a partial just a curry
that hasn't filled in all the arguments yet?

~~~
chriswarbo
I assume you mean "partial application"?

"Currying" turns a multi-argument function into a chain of one-at-a-time
wrappers. If we curry a 5-argument function "foo(a, b, c, d, e)", we get a
nesting of 5 functions, each accepting one argument "foo(a)(b)(c)(d)(e)". The
implementation in the article, as well as my own, go slightly further and
_also_ allow curried functions to accept multiple arguments at once, eg.
"foo(a, b, c, d, e)"; this is just for convenience though, a "real" curried
function must accept arguments one at a time. Note that in Haskell syntax,
there is no difference between the two: "foo a b c d e".

Alternatively, "partial application" takes some argument values now, returning
a function which accepts the rest later. If we partially-apply a 5-argument
function with, say, its first 2 arguments, we get back a 3-argument function,
eg. "papply(foo, a, b)(c, d, e)".

Note that we must use partial application explicitly whenever we want to
supply a few more arguments; curried functions keep track of this themselves.

As an aside, you mention Haskell. Note that Haskell functions are already
curried; in Haskell, "curry" and "uncurry" convert between functions which
accept separate arguments and functions which accept one big tuple of
arguments.

------
rpwverheij
being a javascript/typescript developer with little knowledge about functional
programming, this article renewed my interest in the matter. I would be
interested to see some performance tests though, to get a feeling just how
much 'a little performance cost' costs

~~~
visarga
Me too. I thought long and hard about how I could use functional programming
(aside from the usual callbacks) and came to the conclusion that functional
programming is more composable - that's its strength - how you can combine
stages in a pipeline. It's all centered around data flow instead of execution
flow.

One example would be jQuery or Underscore - how you can chain operations with
the "." operator, or another common example is how we use the pipe " | "
operator in the shell to compose processes. I use the latter quite a lot and
am proficient at making pipelines.

By contrast, procedural programming relies a lot on global variables and that
makes a mess of reusing pieces of code from an app into another.

~~~
chriswarbo
I wouldn't say that procedural code relies on global variables, but I would
say that we find ourselves worrying about execution order a lot more when
using procedures rather than pure functions.

If we care about execution order, we tend to avoid higher-order patterns which
may defer execution (eg. compose) or give a nondeterministic order (eg. map).
If we avoid higher-order patterns, we end up hard-coding an awful lot of
control-flow, which makes our code less re-usable.

Simplistic attempts to avoid this, introduce a small amount of higher-order
behaviour, like passing around 'callbacks', but this can be cumbersome and add
a lot of boilerplate. Of course, the solution to avoiding this is to use even
more powerful higher-order functions (like monadic bind) to handle the
callbacks for us, but since we're trying to avoid as much higher-order
behaviour as possible, this tends not to be done.

------
batmansbelt
Seems like a cool use of the technology.

