Currying in the real world

Written by samuelpouyt | Published 2017/04/16
Tech Story Tags: functional-programming | javascript | nodejs | tutorial

TLDRvia the TL;DR App

When I started to learn functional programming, I learned a lot of interesting concepts. But I was wondering where I could use them in the real world. Indeed, most tutorial give examples of those concepts in simple code:

Nice, this works, but I rarely write addition in my code. I could use this to increment something with a addOne()function. But most language have an easy way of doing this i++ or i += 1. Why bother?

Let’s review this code nevertheless. The first line creates a function add() that takes one parameter and it returns another function that also takes one parameter. The returned function already has a value for a, and is waiting for a b value. That second function adds the first and the second parameter and returns the result. To make it clear, that first line could be written as follow:

You clearly see the benefit of the less verbose ES6 syntax… You can call this function in two ways: the one I have just shown you: const addTwo = add(2) and const result = add(2)(2) . The first example is an example of currying and it is more or less the example you will see in many tutorials. The second one is actually giving you a result (4).

Currying is:

the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument.

Ok… I have created a function addTwo() that will always add two to any int that you will give it. And concatenate a string to two if you give it a string…

Fine… what do I do with this. Where can currying be useful in the real world. Let’s do some refactoring:

This is method in a small library that help me parse data coming from an API first CMS (Cloud CMS). I need to format dates as per the corporate guideline, parse markdown, create documents and images url. This is the method that parses those urls.

This method maps all the returned objects from the API, then maps each properties and parses the appropriate ones. Let’s apply the knowledge we now have about currying to refactor this method. Notice that on line 8, 15, 20 and 24 we call the same function again and again with slight parameter variations: self.attachementUrl() . This function takes 3 arguments and two optional ones. First a baseUrl , then a type of attachement and the attachement object. (attachement is a Cloud CMS concept where a document is attached to a node, and linked with a relation that can be followed. Cloud CMS uses a graph database). The optional arguments are size and mimetype .

This is our opportunity to curry some functions! What we can do is create a function like the add() one that we have seen and two partially applied functions that we will use in the code:

The function parse() takes first the baseUrl , then the type (preview or static) and then two arguments attachement and size . We can pass them together, because we know that we format the images for each case with a specific size. When we call self.attachementUrl() we do the actual work, this is the a + b of the basic example.

Then we can create two partially applied functions: parsePreview() and parseStatic() . These two functions correspond to the addTwo() function we saw earlier. We partially apply two arguments that will not change, and we leave the two other ones to be used in the code specifically.

Thus we can replace our previous code with the following:

On line 12, 19, 24, 28 we give the last arguments to our partially applied functions. In this example we did not reduce the amount of lines, but by using curried functions, we improve maintainability of our code as we repeat ourselves less. I think this is one of the aim of functional programming: have a code that is more maintainable, by using small functions, that do one thing, but that do it reliably.

This code is a little in between, as this was the first time I saw the opportunity to curry a function in my code. But now I try to apply functional programming as much as possible, even within Object Oriented projects.

To finish on an historical note, have you ever wondered why currying is called currying? Actually it has nothing to do with India. It simply a reference to the mathematician and logician Haskell Brooks Curry.

Thanks to apy for his comment.


Published by HackerNoon on 2017/04/16