
How currying leads to elegant, readable code - CrossEye
http://fr.umio.us/favoring-curry/
======
KMag
If I'm writing a function where there isn't an obvious order for the
arguments, I chose the order such that Currying is most useful, even if the
language I'm writing in doesn't support Curried functions/partial function
application. You never know when someone will port your code or create cross-
language bindings.

For instance, my company writes a lot of code in a proprietary language and
the other day I was writing a function to generate random strings, given a
length and an "alphabet" string from which to choose characters.

I chose the ordering:

    
    
        randomString alphabet length = ...
    

so that if partial function application were added to the language, one could
simply write the functions randomHex and randomBase32 as:

    
    
        randomHex = randomString "0123456789ABCDEF"
        randomBase32 = randomString "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
    

The alternative ordering would allow me to easily write functions that
generate fixed length strings and take their alphabets as inputs:

    
    
        random10Char = randomString 10
        random4Char = randomString 4
    

This ordering is much less useful in general, so I chose to make the alphabet
the first parameter.

On a side note, our language also has some time series extensions for dataflow
programming. There's an API for efficiently adding new data flows based on
something similar to template specialization, but the API is unwieldy and the
source of much confusion. So, I wrote a wrapper API that uses reflection to
expose the same functionality as partial function application / Curried
functions over time series.

~~~
joeyh
It's an interesting design question to pick orderings that work best with
currying.

Oddly though, when writing haskell code, I don't worry about it much. Once I
find myself needing to `flip` a function before using it, I have determined
experimentally that the original parameter order I picked was not the best
one, and I then go change the function, and let the type checker walk me
through fixing any necessary call sites (which also verifies if the new
parameter order is better or not).

~~~
mikeash
I wonder why languages don't support currying arbitrary parameters.

It seems like it would be easy enough to have a special "placeholder" keyword
that means "these parameters will be the parameters of the curried function".
To take his example:

    
    
        var jp = formatNames2('John', 'Paul');
    

That might be written like this instead:

    
    
        var jp = formatNames2('John', 'Paul', _);
    

And then if you want to curry the second parameter instead of the third, it's
easy:

    
    
        var jp = formatNames2('John', _, 'Jones');
    

Or maybe they do and I just haven't heard of it?

~~~
malisper
Clojure[0] and Anarki[1] (public fork of Arc) both provide a way to do this
(with more than one argument as well). They both have syntax for a "literal
function". Your second example would become:

Arc/Anarki: [format-names2 "John" _ "Jones"] which expands to (fn (_) (format-
names2 "John" _ "Jones"))

Clojure: #(format-names2 "John" % "Jones") which expands to (fn (%) (format
names2 "John" % "Jones"))

Then for a function of two arguments that curried the middle one:

Anarki: [format-names2 _1 "Paul" _2] which expands to (fn (_1 _2) (format-
names2 _1 "Paul" _2))

Clojure: #(format-names2 %1 "Paul" %2) which expands to (fn [%1 %2] (format-
names2 %1 "Paul" %2))

[0] [http://clojure.org/reader](http://clojure.org/reader) [1]
[https://github.com/arclanguage/anarki/blob/master/CHANGES/ma...](https://github.com/arclanguage/anarki/blob/master/CHANGES/make-
br-fn)

~~~
mikeash
I should have known that if I can imagine a language feature, it will already
be implemented in the Lisps....

------
pettazz
_Currying is the process of turning a function that expects multiple
parameters into one that, when supplied fewer parameters, returns a new
function that awaits the remaining ones._

I think this, along with the whole article, is the best explanation of
currying I've seen on the whole damn internet.

~~~
cowbell
It's also wrong :)

[http://www.uncarved.com/blog/not_currying.mrk](http://www.uncarved.com/blog/not_currying.mrk)

Which the author freely admits:

(Some will insist that what we're doing is more properly called "partial
application", and that "currying" should be reserved for the cases where the
resulting functions take one parameter, each resolving to a separate new
function until all the required parameters have been supplied. They can please
feel free to keep on insisting.)

~~~
tel
As long as you have ordered parameters, I'm not sure this is such a big issue.
First, tuples are (morally, i.e. up to non-termination) associative in most
reasonable languages, so the product/exponential adjunction can be shifted
around however you like

    
    
        -- all morally identical
        a ->  b -> c   -> d
        a -> (b -> c   -> d)
        a -> (b -> (c -> d))
        (a, b)  -> c   -> d
        (a, b, c)      -> d
        ((a, b), c)    -> d
        (a, (b, c))    -> d
    

However, so long as you have parameter order (we're not allowed to commute our
tuples, just reassociate nested tuples like ((a, b), c) <-> (a, (b, c)) and so
on) then flip still morally works

    
    
        flip (someFn :: (a, b, c) -> d)
          :: (b, a, c) -> d
          :: (b, a) -> c -> d
          :: b -> a -> (c -> d)
    

The same story holds for partial evaluation. Of course, there have to be _far_
more edge cases to handle all this tuple twiddling.

\---

Really, I think it's pretty meaningful to blur the distinction between "curry
(once)" and "curry repeatedly along with tuple reassociation". The later forms
an equivalence class of function types which all have the same application
behavior.

~~~
tel
Also to explain that strange "adjunction" comment, currying results from the
notion that the things of type

    
    
        (a, b) -> c
    

are exactly equivalent to the things of type

    
    
        a -> (b -> c)
    

An adjunction (F, G) occurs when the things of type (F a -> c) are equivalent
to things of type (a -> G c), so if we pick F x = (x, b) and G x = (b -> x)
then we see that currying is an adjunction between (,b) and (b ->).

~~~
evincarofautumn
One intuition for this is that (a, b) is the product type (a × b) and the
function arrow (a → b) corresponds to exponentiation (b^a), so you get the
isomorphism for free from the identity c^(a × b) = (c^b)^a.

------
twic
Is the final code equivalent to:

    
    
      var getIncompleteTaskSummaries = function(membername) {
        return fetchData().then(function(data) {
          var incompleteTasks = [];
          for (i = 0; i < data.tasks.length; ++i) {
            var task = data.tasks[i];
            if (task.username == membername && !task.complete) {
              incompleteTasks.push({id: task.id, dueDate: task.dueDate, title: task.title, priority: task.priority});
            }
          }
          incompleteTasks.sort(function(a, b) {
            return a.getTime() - b.getTime();
          });
          return incompleteTasks;
        });
      }
    

?

Apologies if that's wrong, i barely know JavaScript.

That code is not so great, and a bit '90s, but it's not appalling. The
horrifically verbose non-currying code in the article isn't something i see
any need to write. It looks like an outrageous strawman to me.

My code here could definitely improved with some functional idioms for the
looping, picking, and sorting, but i wouldn't reach for currying here.

~~~
skybrian
This is perfectly good style, and better than the original article. Don't
listen to the functional language fans. Replacing the for loop with its
functional equivalents would make it less readable.

~~~
jamii
Currying with map/reduce/filter can be hard to read, but list comprehensions
are pretty nice:

    
    
       (defn get-imcomplete-task-summaries [membername]
          (.then (fetch-data)
                 (fn [data]
                   (sort-by :time
                            (for [task (:tasks data)
                                  :when (= membername (:username task))
                                  :when (not (:complete task))]
                              task ;; immutable, no need to copy
                              )))))
    

It makes me a little sad that functional programming has come to mean
map/reduce/filter for lots of people, rather than avoiding mutation which is
far more interesting.

~~~
skybrian
Well, avoiding mutation can be helpful but it's not a rule to be followed
blindly either. A mutable local variable never hurt anyone, so long as it
doesn't leak out of the function.

~~~
daemonize
Even in a multiple-thread scenario?

~~~
twic
As an aside, one of the really interesting ideas that's bubbling up from Rust
is that it's not mutable state that's a problem, it's shared mutable state,
and that you can make it safe by removing the sharing, rather than removing
the mutability:

[http://smallcultfollowing.com/babysteps/blog/2014/05/13/focu...](http://smallcultfollowing.com/babysteps/blog/2014/05/13/focusing-
on-ownership/)

I have no idea if this is true, but it's going to be really interesting to see
that idea tried.

------
orkoden
Currying can be hard to spot if you're not used to it. Especially in a
language with inferred or dynamic type, it's not obvious that the var contains
a function, not a result object.

var result = somefunc(a,b) // object var otherResult = somefunc(a) // function

It gets even more confusing if overloading of function names for different
parameters or different number of parameters is allowed.

So elegant: maybe. Readable: no. Depends on the programming language.

~~~
CrossEye
I don't think currying can reasonably be combined with optional parameters. At
least I've never seen a useful way to do so.

In a previous article ([http://fr.umio.us/why-ramda/](http://fr.umio.us/why-
ramda/)) I discuss more thoroughly how I would tend to use this currying,
namely to build up collections of useful functions, often in points-free
style, so that major parts of the application would end up as (ideally well-
named) functions, each which serve as pipelines of these smaller functions,
passing data through the system.

I do find this significantly more readable, but _de gustibus non est
disputandum_.

~~~
polm23
I've never used that particular feature, but Livescript lets you use default
arguments on curried functions by calling with no arguments.

[http://livescript.net/#functions](http://livescript.net/#functions)

~~~
tel
Which implies there's a distinction between "siphoning arguments around" and
"application". That feels very weird.

------
faldore
"Ok, here we go. Does code like this look at all familiar?"

No, because I use Array.prototype.filter(), Array.prototype.map(), and
Array.prototype.reduce() to accomplish these things...

~~~
CrossEye
Yeah, I probably shouldn't have cribbed the example from my old "Intro to
Functional Programming" talk...

------
dustingetz
Basic point free style as described in the article is alright in javascript.

Extreme point free style does not work in javascript, AT ALL!!!! Two reasons:

1) Find the bug: the table sort is glitchy. Is the bug in this suspicious
line, or somewhere else? (Real line of code in a codebase I inherited, and yes
there is a bug in it)

    
    
        var sorted = rows.sort(_.unsplat(_.pipeline(
            _.partial(_.map, _,  accessor), 
            _.splat(comparator))));
    

2) I use React, so I can get away with a lot of really functional stuff since
React is well suited for functional javascript. React is a great functional
abstraction, but under the abstraction is imperative code. Imperative code
means you need a debugger. When you write in a point free style, there's
nowhere to place a breakpoint!

~~~
CrossEye
It is harder to debug points-free code. I find myself doing more debugging
with `log` statements in a long pipeline than I do with other styles of code.

On the other side, I tend to work with a few well-tested functions over and
over and end up with fewer problems to debug when I work in a functional
paradigm, points-free or not.

On rare occasions, when I need to debug something that is difficult __because
__it 's points-free I simply add some explicit parameters, either temporarily
to enable debugging or permanently.

Points-free is nice, but should never be an overriding goal.

------
anon4
I'm generally a fan of currying, but specifically when used with javascript, I
think it can be problematic. The default behaviour of any function when called
with fewer arguments than specified is to set named arguments to undefined.
Meaning, functions in javascript always take any number of arguments and
changing that default behaviour is confusing. There is also the matter of the
"this" parameter.

I think that using the .bind() method on functions is the right approach. It
will lead to less surprising behaviour in the context of javascript.

------
aaronblohowiak
Currying is the factory factory pattern for λ people.

------
Finster
The "curried" code seems less readable and maintainable than the original
code. Is this like dependency injection where I have to make my code harder to
read and maintain to satisfy some technical definition of "loosely" couple?

~~~
aResponder23
It'll seem less readable at first, yes. I've seen a codebase transformed by
currying. We were able to remove six functions from one webservice interaction
service, and handfuls throughout other parts of the code, and have made
debugging and maintenance easier.

The code is a little more confusing at first glance. The developers who
replaced the code with curried functions didn't inform the whole team what
they were doing. There were a lot of wtfs until they clarified. Now we can
read it, and I know I'll be looking for places for partial applications.

------
liricooli
I have no experience neither with JS nor with functional programming, but know
Lambda calculus and currying from Discrete math courses.

As Currying and functional programming a popular thing now, I was thinking
what my current codebase would look like in C# if I were writing code in a
more functional way.

So, obviously C# isn't a functional languageat all but using Func<T>, and
maybe some delegates would enable this easily.

I'm not sure this would turn my code to more elegant or readable.

What would I benefit from ?

~~~
CrossEye
I'm not really a C# person, but from what I know of the language, although it
has some lambdas and some other functional features especially around LINQ,
functional programming really is against the grain of the language, and would
not be easy to integrate into the same code.

The .NET platform of course has F#, which is a dedicated functional language.
Some day I'll spend some time learning this one... perhaps.

------
detrino
Note that currying is not necessary for partial application, here is partial
application implemented in C++14: [http://coliru.stacked-
crooked.com/a/bed4a4fdd6e856b0](http://coliru.stacked-
crooked.com/a/bed4a4fdd6e856b0)

However, I find lambdas with the extra parameters repeated more readable than
partial application.

------
Demiurge
I'm probably missing something, but why not just do...?

    
    
      var jp = function(last){
          return formatNames2('John', 'Paul', last);
      }

~~~
CrossEye
You can if you want:

    
    
        var jp = function(last) {
            return formatNames2('John', 'Paul', last);
        };
        var je = function(last) {
            return formatNames2('James', 'Earl', last);
        };
        var lh = function(last) {
            return formatNames2('Lee', 'Harvey', last);
        };
        var c = function(middle, last) {
            return formatNames('Clarabelle', middle, last);
        };
    

But I find this cleaner:

    
    
        var jp = formatNames2('John', 'Paul'};
        var je = formatNames2('James', 'Earl'};
        var lh = formatNames2('Lee', 'Harvey'};
        var c = formatNames('Clarabelle'};

~~~
Demiurge
Should you really have jp je lh and c at all than? Having so many different
functions seems like a problem on its own, and maybe there should just be an
array of names and a function iterating over them...

~~~
CatMtKing
It's a toy example; he's just trying to show how currying works, rather than
why you should use it.

If anything, it does show that one useful thing about partial application is
that you can write a generic function (formatNames) and then make it more
specific (formatNames("John")) without repeating yourself.

~~~
Demiurge
I think I understand how it works, I just haven't seen examples that
demonstrate why it is useful.

~~~
ajuc
Say you want to calculate distances from origin to each point in array, and
keep only these greater than R.

Using fors and ifs:

    
    
        var origin = Point(0, 0);
        var R = 100;
        var result = [];
        for (var i : array) {
            tmp = distance(array[i], origin);
            if (tmp>R) {
               result.append(tmp);
            }
        }
    

Without currying (nobody would write it that way):

    
    
        var origin = Point(0, 0);
        var R = 100;
        result = filter( map(array, function (x) { return distance(x, origin); }),
                         function (x) { return greater(x, R);} );
    

With currying it almost reads like SQL:

    
    
        var origin = Point(0, 0);
        var R = 100;
        result = filter( map(array, distance(origin)), greater(R) );
    

It's useful for functions that you predict will be used many times with one of
the arguments the same. Yes, it's just syntactic sugar, but it sometimes makes
code clearer (especially when literal function syntax is as verbose as in
javascript).

~~~
CrossEye
A nice example. Thank you.

I just want to note that in Ramda, because of it's strong insistence on a
data-last API (which makes the currying easier), this would be written in this
order:

    
    
        result = filter(greater(R), map(distance(origin), array));
    

But it's precisely the same idea.

------
donpdonp
Upvoted just for the quality of the pun.

~~~
CrossEye
Have to thank/blame @buzzdecafe for that!

------
phillc73
I favour a nice hot Rogan Josh. Helps me write excellent code the next
morning. Not so the half a dozen pints I had along with it.

