Currying
In the previous lecture, higher order function, we have created a sum
function.
def sum(fn: Int => Int, x: Int, n: Int): Int = {
def loop(x: Int, acc: Int): Int = {
if (x > n) acc
else loop(x + 1, acc + fn(x))
}
loop(x, 0)
}
def sumInts(a: Int, b: Int) = sum(x => x, a, b)
def sumSquare(a: Int, b: Int) = sum(x => x * x, a, b)
We notice that a
and b
is passed unchanged to each function. The question is, can we avoid this replication?
Currying
def sum(fn: Int => Int): (Int, Int) => Int = {
def sumF(x: Int, n: Int): Int = {
if (x > n) 0
else fn(x) + sumF(x + 1, n)
}
sumF
}
def sumInts = sum(x => x)
sumInts(1, 10)
def sumSquare = sum(x => x * x)
sumSquare(1, 10)
Currying is very common in Functional Programming. Scala has a syntax sugar for it.
def sum(fn: Int => Int)(x: Int, n: Int) = {
if (x > n) 0
else fn(x) + sum(fn)(x + 1, n)
}
Function Type
Question: What's the type of sum
.
It's (Int => Int) => (Int, Int) => Int
.
Notice that Function Type assoicates to the right.
Int => Int => Int
equals to Int => (Int => Int)
Exercise
Let's generalise sum
function to mapReduce
.
def mapReduce(mapper: Int => Int, reducer: (Int, Int) => Int, initValue: Int)(x: Int, n: Int) = {
def recur(x: Int): Int = {
if (x > n) initValue
else reducer(mapper(x), recur(x + 1))
}
recur(x)
}
Now, the sum
is:
def sum(fn: Int => Int) = mapReduce(fn, (x, y) => x + y, 0)
// Other functions that we can create
def product(fn: Int => Int) = mapReduce(fn, (x, y) => x * y, 0)