- 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
Exercises
Write a function values(fun: (Int) => Int, low: Int, high: Int) that yields a collection of function inputs and outputs in a given range. For example, values(x => x * x, -5, 5) should produce a collection of pairs (-5, 25), (-4, 16), (-3, 9),..., (5, 25).
How do you get the largest element of an array with reduceLeft?
Implement the factorial function using to and reduceLeft, without a loop or recursion.
The previous implementation needed a special case when n < 1. Show how you can avoid this with foldLeft. (Look at the Scaladoc for foldLeft. It’s like reduceLeft, except that the first value in the chain of combined values is supplied in the call.)
Write a function largest(fun: (Int) => Int, inputs: Seq[Int]) that yields the largest value of a function within a given sequence of inputs. For example, largest(x => 10 * x - x * x, 1 to 10) should return 25. Don’t use a loop or recursion.
Modify the previous function to return the input at which the output is largest. For example, largestAt(x => 10 * x - x * x, 1 to 10) should return 5. Don’t use a loop or recursion.
Write a function that composes two functions of type Double => Option[Double], yielding another function of the same type. The composition should yield None if either function does. For example,
def f(x: Double) = if x != 1 then Some(1 / (x - 1)) else None def g(x: Double) = if x >= 0 then Some(sqrt(x)) else None val h = compose(g, f) // h(x) should be g(f(x))
Then h(2) is Some(1), and h(1) and h(0) are None.
Section 12.9, “Methods for Composing, Currying, and Tupling,” on page 177 covers the composing, currying, and tupling methods that all functions have. Implement these from scratch, as functions that operate on integer functions. For example, tupling(mul) returns a function ((Int, Int)) => Int, and tupling(mul)((6, 7)) is 42.
What does the curried method do for a method with more than two parameters?
In Section 12.8, “Currying,” on page 176, you saw the corresponds method used with two arrays of strings. Make a call to corresponds that checks whether the elements in an array of strings have the lengths given in an array of integers.
Implement corresponds without currying. Then try the call from the preceding exercise. What problem do you encounter?
Implement an unless control abstraction that works just like if, but with an inverted condition. Does the first parameter need to be a call-by-name parameter? Do you need currying?