- Higher order functions
- Tail call optimization
- Currying
2.1) Three Fibonacci implementations
def fibs(x: Int): Long = {
if (x <= 0) 0
else if (x == 1) 1
else fibs(x-1) + fibs(x-2)
}
def fibsTailRec(x: Int): Long = {
@annotation.tailrec
def loop(n: Int, last: Long, current: Long): Long = {
if( n == x ) last
else loop(n + 1, current, current + last)
}
loop(0, 0, 1)
}
def lazyFibs: Stream[Long] =
0L #:: 1L #:: lazyFibs.zip(lazyFibs.tail).map { case (first, second) => first + second }
2.2) Polymorphic Sorted
def isSorted[A](as: Array[A], ordered: (A,A) => Boolean): Boolean = {
as.zip(as.tail).forall{case(a,b)=> ordered(a,b)}
}
def orderedStrings(a: String, b: String) = a < b
isSorted(Array("a"), orderedStrings)
isSorted(Array("a","b","c"), orderedStrings)
isSorted(Array("a","b","a"), orderedStrings)
isSorted(Array("d","b","c","a"), orderedStrings)
2.3) Curry
def curry[A,B,C](f: (A, B) => C): A => B => C = {
(a: A) => (b: B => f(a, b))
}
2.4) Uncurry
def uncurry[A,B,C](f: A => B => C): (A, B) => C = {
(a: A, b: B) => f(a)(b)
}
2.5 Compose
def compose[A,B,C](f: B => C, g: A => B): A => C ={
a: A => f(g(a))
}