Alex

Chapter 2

Scala Introduction - Various Notes

Objects and Namespaces

Higher Order Functions

Tail Call Optimisation

def factorial(n: Int): Int =
  def go(n: Int, acc: Int): Int =
    if n <= 0 then acc
    else go(n-1, n*acc)
  go(n,1)
def fib(n: Int): Int =
  if n == 0 then return 0
  if n == 1 then return 1
  
  @tailrec
  def go(n: Int, prev: Int, curr: Int): Int =
    if n == 2 then prev + curr
    else go(n - 1, curr, prev + curr)

  go(n, 0, 1)

// book implementation is simpler: 
def fib(n: Int): Int =
  @tailrec
  def go(n: Int, current: Int, next: Int): Int =
    if n <= 0 then current
    else go(n - 1, next, current + next)
  go(n, 0, 1)

Higher Order Functions

def formatResult(name: String, n: Int, f: Int => Int) =
  val msg = "The %s of %d is %d."
  msg.format(name, n, f(n))

Polymorphic Functions

def findFirst[A](as: Array[A], p: A => Boolean): Int =
  @tailrec
  def loop(n: Int): Int =
    if n >= as.length then -1
    else if p(as(n)) then n
    else loop(n+1)

Anonymous Functions (Lambdas, Function Literals)

findFirst(
  Array(7,9,13),
  (x: Int): Boolean => x == 9 // the : Boolean here is optional - Scala can infer this
)
def isSorted[A](as: Array[A], gt: (A, A) => Boolean): Boolean = {
  @tailrec
  def go(i: Int): Boolean =
    if i >= as.length - 1 then true
    else if gt(as(i), as(i + 1)) then false
    else go(i + 1)

  if as.length <= 1 then true else go(0)
}

println(isSorted(Array(1,2,3), _ > _))
def partial1[A,B,C](a: A, f: (A,B) => C): B => C = 
  (b: B) => f(a, b)

def curry[A, B, C](f: (A, B) => C): A => (B => C) =
  (a: A) => (b: B) => f(a,b)

// => is right associative so A=>B=>C is equivalent to A=>(B=>C)
def uncurry[A, B, C](f: A => B => C): (A, B) => C =
  (a: A, b: B) => f(a)(b)
def compose[A, B, C](f: B => C, g: A => B): A => C = 
  (a: A) => f(g(a))

Summary