Function currying is an interesting concept in Scala. We often associate it with the partially applied functions. Let's try to understand the basics with an example. Let me start with the example that I used to discuss partially applied functions in the previous section.
def sumOfX(f: Int=> Int, a:Int, b:Int):Int = if (a>b) 0 else f(a) + sumOfX(f, a+1, b)
When I already know that I am going to use the sumOfX to create multiple partially applied functions. Instead of using this syntax, I will use parameter grouping. I can revise the above code as shown below.
def sumOfX(f: Int=> Int) (a:Int, b:Int):Int = if (a>b) 0 else f(a) + sumOfX(f) (a+1, b)
I have broken the parameter list into two groups. The first group takes the
function literal. The second group takes the
lower and upper bounds. The syntax for parameter grouping is as simple as passing
group of arguments into a separate pair of parenthesis.
This syntax makes the function definition more readable and easy to follow. However, It also impacts the way we call the function. The following code shows the new method to call the function.
The above syntax is a bit more readable and stylish. Isn't it. Now, if you want to create a partially applied function, you can simply apply a placeholder for the entire group.
val si = sumOfX(x=>x*x*x) _
In the above example, we applied two things.
- Parameter grouping.
- Partially applied function.
We already know that in case of a partially applied function, Scala generates a new function that takes unapplied arguments. When we mix the parameter grouping with partially applied function, the effect of the partial application becomes noticeably visible. Look at the example shown below.
//A Higher order function that returns another function def sumOfY(f: Int=> Int) : (Int, Int)=>Int = (a:Int, b:Int)=> if (a>b) 0 else f(a) + sumOfX(f) (a+1, b) //You can call it as below sumOfY(x=>x*x)(1,5) //This is exactly same as sumOfX shown in earlier example sumOfX(x=>x*x)(1,5)
In the above example, sumOfY is neither using a parameter grouping nor it
using a partial application. The sumOfY is purely a Higher Order function
returns another function.
However, SumofX is also the same thing. That's what I meant when I said that the effect of the partially applied function becomes noticeable visible. Just looking at the last line in above example, you can clearly tell that the function sumOfX takes one argument and it returns a function that takes two arguments, and we are calling a chain of functions.
Parameter grouping and the partially applied function together create an effect
that we refer as function currying. In fact,
the function currying is nothing but a syntactic sugar. It allows us to explicitly
that we are calling a chain of functions. The call to sumOfX
explicitly tells that we want to call two functions in a chain.
So, the function currying allows you to split your function parameters into multiple groups. Scala will internally generate a series of functions for each argument group. That's what we want in partially applied functions. So, we often use it with partially applied functions.
Basics of Scala functions | Function Literals in Scala | Function values | Local Functions | Variable length argument | Default values and named arguments | Scala Placeholder syntax | Higher Order functions | Partially applied functions | Function currying