- 12.1 Functions as Values
- 12.2 Anonymous Functions
- 12.3 Parameters That Are Functions
- 12.4 Parameter Inference
- 12.5 Useful Higher-Order Functions
- 12.6 Closures
- 12.7 Interoperability with Lambda Expressions
- 12.8 Currying
- 12.9 Methods for Composing, Currying, and Tupling
- 12.10 Control Abstractions
- 12.11 Nonlocal Returns
- Exercises
12.9 Methods for Composing, Currying, and Tupling
A unary function is a function with one parameter. All unary functions are instances of the Function1 trait. That trait defines a method for composing two unary functions—that is, executing one and then passing the result to the other.
Suppose we want to be sure that we don’t compute square roots of negative values. Then we can compose the square root function with the absolute value function:
val sqrt = scala.math.sqrt val fabs: Double => Double = scala.math.abs // Need the type because abs is overloaded val f = sqrt compose fabs // Infix notation; could also write sqrt.compose(fabs) f(-9) // Yields sqrt(fabs(-9)) or 3
Note that the second function is executed first, because functions are applied right to left. If you find that unnatural, use the andThen method instead:
val g = fabs andThen sqrt // The same as sqrt compose fabs
Functions with more than one parameter have a curried method, producing the curried version of a function.
val fmax : (Double, Double) => Double = scala.math.max // Need the type because max is overloaded fmax.curried // Has type Double => Double => Double val h = fmax.curried(0)
The function h has one parameter, and h(x) = fmax.curried(0)(x) = fmax(0, x). Positive arguments are returned, and negative arguments yield zero.
The tupled method turns a function with more than one parameter into a unary function receiving a tuple.
val k = mul.tupled // Has type ((Int, Int)) => Int
When calling k, you supply a pair whose components are passed to mul. For example, k((6, 7)) is 42.
This sounds abstract, but here is a practical use. Let’s say you have two arrays, holding the first and second arguments.
val xs = Array(1, 7, 2, 9) val ys = Array(1000, 100, 10, 1)
Now we want to pass corresponding elements to a binary function such as mul. An elegant solution is to zip the arrays, and then apply the tupled function to the pairs:
xs.zip(ys).map(mul.tupled) // Yields Array(1000, 700, 20, 9)