# Functions as Values

• A function is a “first-class citizen”, just like a number:
```import scala.math._
val num = 3.14 // type: Double
val fun = ceil _ // type: (Double) => Double ```
• What can you do with a function?
• Call it
• Store it
• Give it to another function/method
• To call a function, use `()`:
```fun(num) // 4.0; that's ceil(3.14)
```
• Here is how to give a function to another function/method:
`Array(3.14, 1.42, 2.0).map(fun) // Array(4.0, 2.0, 2.0)`

# Anonymous Functions

• You don't give each number a name: `y = x * 2` and not `val factor = 2; y = x * factor`
• You don't need to give each function a name:
```Array(3.14, 1.42, 2.0).map((x: Double) => 3 * x) // Array(9.42, 4.26, 6.0)
```
• Of course, you can store the function in a variable:
`val triple = (x: Double) => 3 * x`
• Same as a `def`:
`def triple(x: Double) = 3 * x`
• Only give a function a name if you need it multiple times.

# Functions with Function Parameters

• Some functions/methods have function parameters:
```def valueAtOneQuarter(f: (Double) => Double) = f(0.25)
```
• Note that the parameter `f` has type `(Double) => Double`.
• Usage examples:
```valueAtOneQuarter(ceil _) // 1.0
valueAtOneQuarter(sqrt _) // 0.5 (because 0.5 × 0.5 = 0.25)```
• Type of `valueAtOneQuarter`:
`((Double) => Double) => Double`
• `valueAtOneQuarter` is a higher-order function: It is a function that consumes a function

# Functions That Produce Functions

• A function can produce another function:
`def mulBy(factor: Double) = (x: Double) => factor * x`
• For example, `mulBy(3)` returns `(x: Double) => 3 * x`.
• That's the function that we previously stored in `triple`.
• We can produce a function with any multiplier:
```val quintuple = mulBy(5)
quintuple(20) // 100```
• Type of `mulBy:`
`(Double) => ((Double) => Double)`

# Parameter Inference

• Scala can deduce types:
`valueAtOneQuarter((x) => 3 * x)`
`valueAtOneQuarter((x: Double) => 3 * x)`
• Special bonus: Can omit `()` if there is just one parameter:
`valueAtOneQuarter(x => 3 * x)`
• If the parameter variable occurs just once, can replace with `_`:
`valueAtOneQuarter(3 * _)`

# Map, Filter, Reduce

• `map` applies a function to each element of a sequence:
```(1 to 9).map(0.1 * _) // 0.1, 0.2, . . . , 0.9
```
• `filter` retains the elements that fulfill a predicate:
`(1 to 9).filter(_ % 2 == 0) // 2, 4, 6, 8`
• `reduceLeft` applies a binary function, going from left to right:
`(1 to 9).reduceLeft(_ * _) // (...((1 * 2) * 3) * ... * 9)`
• You have seen `map` and `filter` before:
`(1 to 9).filter(_ % 2 == 0).map(0.1 * _)`
is the same as
`for (n <- 1 to 9 if n % 2 == 0) yield 0.1 * n`

# Closures

• A function has access to any variable from any enclosing scope...
• ...even if the variable is no longer around when you call the function!
• Consider this in slow motion:
```def mulBy(factor: Double) = (x: Double) => factor * x
val triple = mulBy(3)
triple(14) // Yields 42
```
1. When calling `mulBy(3)`, `factor` is set to 3.
2. When `mulBy(3)` returns, `triple` is set to the function...
3. ...and the parameter variable `factor` is gone.
4. When `triple(14)` is called, `factor * 14` is computed.
• The function “captures” the variables that it needs.
• Implemented as objects with instance variables for captured variables.

# Currying

• Currying = turning a function that takes two arguments into a function that takes one argument.
• That function returns a function that consumes the second argument.
• Huh?
• Compare
```def mul(x: Int, y: Int) = x * y
```
and the “curried” version:
`def mulOneAtATime(x: Int) = (y: Int) => x * y`
• `mulOneAtATime(3)` is the function `y => 3 * y`.
• `mulOneAtATime(3)(14)` is 42.
• Syntactic sugar:
`def mulOneAtATime(x: Int)(y: Int) = x * y`

# Currying for Type Inference

• The `corresponds` method compares whether two sequences are the same under some comparison criterion:
```val a = Array("Hello", "World")
val b = Array("hello", "world")
a.corresponds(b)(_.equalsIgnoreCase(_)) // true```
• Note the currying:
`a.corresponds(b)(_.equalsIgnoreCase(_))`
• The method is declared like this:
`def corresponds[B](that: Seq[B])(p: (A, B) => Boolean): Boolean`
• When the compiler sees `a.corresponds(b)`, it can infer the type `B` as `String`.
• Then you can omit the parameter types on the predicate.
• Without currying, it would have to be like this:
```a.corresponds(b, (sString, tString) => s.equalsIgnoreCase(t))
```

# Control Abstractions

• Can model a sequence of statements as a function with no parameters
• Then provide “control abstractions” that manipulate that function
• For example, run some statements in a separate thread:
```runInThread { () =>
}```
• Implementation is straighforward:
```def runInThread(block: () => Unit) {
override def run() { block() }
}.start()
}```
• Avoid the unsightly `() =>` in the call with call by name notation:
```def runInThread(block: => Unit) {
override def run() { block }
}.start()
}
```
• Now the call looks prettier:
`runInThread { println("Hi"); Thread.sleep(10000); println("Bye") }`

# Part 1: Life Without Loops

1. In Scala, we prefer to use higher-order functions instead of loops. Let's explore that with an interesting data set. In a new worksheet, enter the following:
`val zones = java.util.TimeZone.getAvailableIDs`
What do you get?
2. We want to get rid of the continents. Try this:
```zones.map(s => s.split("/"))
```
3. Okay, halfway there. Add a map that takes an array and yields `a(1)`. What did you do? What happens?
4. Hmmm, that's weird. There seem to be arrays of length < 2. How can you find them?
5. Okay, now get rid of them and try again. What did you do?
6. That's a lot of values. Can we get every tenth of them? (Hint: `grouped(10)`)
7. What would it have taken to write that in Java?

# Part 2: Reductions

1. Evaluate
`1.to(10).reduceLeft(_ * _)`
What do you get?
2. Write a function that computes n! in this way.
3. Surely you have written a factorial function before. How did you used to do it? Which approach do you like better?
4. Now we'd like to compute 2n with the same trick. How can you get a sequence of `n` copies of the number 2? Hint: `map`
5. What is your function that computes 2n?
6. Given a `Seq[String]`, how can you use `reduceLeft` to concatenate them with some separator in between? Write a function `concat(strings: Seq[String], separator: String)` that does this. For example, `concat(Array("Mary", "had", "a", "little", "lamb"), " ")` should give a string `"Mary had a little lamb"`.

# Part 3: Do-It-Yourself `while`

1. You've seen how to implement a `runInThread` statement in Scala. You can even implement basic control statements such as `while`. We'll have to call it `While` so it doesn't conflict with the Scala keyword. We'll have two arguments, the condition and the body. We start out the ugly way, with zero-arg functions. For example:
```val n = 10
var i = 1
var f = 1
While(() => i < n, () => { f *= i; i += 1 })
```
How do you declare `While`? (Just the header, not the implementation)
2. Now on with the implementation. If the condition is true, execute the body. Then call the function recursively. What do you get when running the code snippet above?
3. Now use by-name parameters so that you can make the call in this way:
```While(i < n, { f *= i; i += 1 })
```
4. It's still a little ugly. Make it so that you can call the following:
`While(i < n) { f *= i; i += 1 }`
Hint: Curry