9.2 Currying
Functions that return other functions are common in functional programming, and many languages define a more convenient syntax for them:
Scala
Listing 9.4: Example of higher-order functions defined through currying.
def greaterThan(bound: Int)(x: Int): Boolean = x > bound def hasID(identity: Long)(project: Project): Boolean = project.id == identity
It might appear as if greaterThan is a function of two arguments, bound and x, but it is not. It is a function of a single argument, bound, which returns a function of type Int => Boolean, as before; x is actually an argument of the function being returned.
Functions written in this style are said to be curried.1 A curried function is a function that consumes its first list of arguments, returns another function that uses the next argument list, and so on. You can read the definition of greaterThan as implementing a function that takes an integer argument bound and returns another function, which takes an integer argument x and returns the Boolean x > bound. In other words, the return value of greaterThan is the function that maps x to x > bound.
Functional programming languages rely heavily on currying. In particular, currying can be used as a device to implement all functions as single-argument functions, as in languages like Haskell and ML. For instance, we tend to think of addition as a function of two arguments:
Scala
def plus(x: Int, y: Int): Int = x + y // a function of type (Int, Int) => Int plus(5, 3) // 8
However, you can also think of it as a single-argument (higher-order) function:
Scala
def plus(x: Int)(y: Int): Int = x + y // a function of type Int => (Int => Int) plus(5) // a function of type Int => Int plus(5)(3) // 8
Curried functions are so common in functional programming that the => that represents function types is typically assumed to be right-associative: Int => (Int => Int) is simply written Int => Int => Int. For example, the function
Scala
def lengthBetween(low: Int)(high: Int)(str: String): Boolean = str.length >= low && str.length <= high
has type Int => Int => String => Boolean. You can use it to produce a Boolean, as in
Scala
lengthBetween(1)(5)("foo") // true
but also to produce other functions:
Scala
val lengthBetween1AndBound: Int => String => Boolean = lengthBetween(1) val lengthBetween1and5: String => Boolean = lengthBetween(1)(5) lengthBetween1AndBound(5)("foo") // true lengthBetween1and5("foo") // true
Before closing this section on currying, we should consider a feature that is particular to Scala (although other languages use slightly different tricks for the same purpose). In Scala, you can call a single-argument function on an expression delimited by curly braces without the need for additional parentheses. So, instead of writing
Scala
println({ val two = 2 two + two }) // prints 4
you can simply write:
Scala
println { val two = 2 two + two } // prints 4
To use this syntax when multiple arguments are involved, you can rely on currying to adapt a multi-argument f unction into a single-argument function. For instance, the curried variant of function plus can be invoked as follows:
Scala
plus(5) { val two = 2 two + 1 }
This is still value 8, as before.
Many functions and methods are curried in Scala for the sole purpose of benefiting from this syntax. The syntax is introduced here because we will encounter some example uses throughout the book, starting with the next section.