For a long time I couldn’t understand currying functions in Scala and how they work. That was really horrible! Occasionally I met the currying functions in the code and wasted too much time on reading them. So finally I decided to learn how they work and where they could be applied.
Let’s start from a definition. A currying function is a function which could accept a fewer number of parameters than are declared, then it returns a function with unused parameters. This definition is totally weird. In order to understand it we need to go through several examples. And be sure that you already know how simple Scala functions work.
The most efficient way to understand the currying is to work with higher-order functions. Let’s look at following code snippet:
def concatenator(w1: String): String => String = w2 => w1 +" "+ w2
What’s going on in the string above? Well, there is declared
concatenator function. It accepts
w1 argument of
String type. It returns another function of
String => String type. Moreover the returning function has its own body
w2 => w1 +" "+ w2.
Now we can see how it works:
As you see we assigned to
heyWord the function. Then we made a call
heyWord("currying"). The result of that call is “Hey currying” string.
After this demonstration we can move further. Keep in mind how we used the function which was returned.
Let’s declare a curried function:
def concatenator(w1: String)(w2: String) = w1 + " " + w2
So parameters in the
concatenator function defined in a separate brackets. How this circumstance affects the function usage? If we want to call it as a normal function we could pass all arguments in the same time and the result will be:
As you see we get the expected output Hey currying string. But what if we don't have all required elements at the moment of first call? In this case we could use underscore or empty curly brackets instead of missed parameters:
In the code sample from the first section of this article we used currying to achieve the same effect. So we assigned the result of the first call to
val heyWord = concatenator("Hey")_
Then we invoked the
heyWord function with the
currying parameter. I think now currying is more or less clear to you. In order to complete this topic I want to provide one more example of a curried function.
What about a curried function that has more than one parameter per set of brackets? It’s easy:
By the way, if you want to specify not to look at the first argument, you could use the following approach:
val isFiveInRange = isInRange(_:Int,_:Int)(5) //isFiveInRange: (Int, Int) => Boolean = <function2> isFiveInRange(0, 10) //true isFiveInRange(-10, 0) //false
Thanks to Luka Jacobowitz for his remarks on this case.
The basics of currying are simple if you are interested in learning them. A more important aspect of them is a practical usage. In this respect I’m not so experienced and I’d like to see your own samples in comments.