Currying is this thing to make add3 functions.

“Currying” isn’t a a foreign concept, but neither has it been a particularly useful concept for me. Everytime I read about currying, it is about that function that accepts 2 numbers and returns a sum of those 2 numbers

function add(x, y) { return x + y }
add(3,2) // => returns 5

and magic happens when

// but if you curry it
add3 = add(3)

// you can use `add3` anytime, anywhere you ever need to add `3` to things!!1!
add3(2) // => returns 5

anytime? anywhere? amazeballs.

Ok ok, if not add3 as illustration, then what? Switching from not-ever-using-it[1] to using-it-multiple-times-recently[2], I’d like to offer a more relevant and practical example

Let’s say we’re trying to process a list of content… e.g. tweets

function processTweet(tweet) {
    return `{tweet.User} says, “{tweet.Text}”`
}

arrayOfResult = map(processTweet, arrayOfTweets)

map will pass each tweet from arrayOfTweets into function processTweet and returns an array of the corresponding result.

So far so good.

Say we want to enhance it with more context and find ourselves needing other things to do the processing, e.g. me or even a db cache — i.e. we want to append a list of common friends

return `{tweet.User} says, “{tweet.Text}”` + sharedBy(db, me, tweet)

So.. how do we get db and me in there? Without currying, we’ll have to settle for inline lambdas with closures; losing our standalone, reusable, test-friendly processTweet function

arrayOfResult = map(function(tweet) {
    return `{tweet.User} says, “{tweet.Text}”` + sharedBy(db, me, tweet)
}, arrayOfTweets)

Oh dear. How about we overcomplicate processTweet to return a function instead?

function processTweet(db, me) {
    return function(tweet) {
        return `{tweet.User} says, “{tweet.Text}”` + sharedBy(db, me, tweet)
    }
}

arrayOfResult = map(processTweet(db, me), arrayOfTweets)

With currying, there is no ceremony — processTweet remains a straightforward function that takes in the required arguments, does the processing, and returns result.

function processTweet(db, me, tweet) {
    return `{tweet.User} says, “{tweet.Text}”` + sharedBy(db, me, tweet)
}

and we use it like it’s a function returning a function, simply by omitting some arguments

arrayOfResult = map(processTweet(db, me), arrayOfTweets)

To me, that’s pretty sweet.

[1] I do closures with lambdas or functions returning functions, but they are different from currying
[2] Elm