Intro to Scala part II.

 A bit more of functional programming.

Lesson plan

  •     Scala functions and methods
    • Function structure
    • Functional concepts - higher order functions (map, filter, fold)
  •     Review of last week exercises
  •     New exercises! Hooray!

Quick recap


// var versus val

scala> val two = 1 + 1
two: Int = 2

scala> var two2 = 1 + 1
two2: Int = 2

// method definition

def addTwo(number: Int): Int = number + 2

// method invocation

scala> addTwo(1)
res2: Int = 3

Functions

(x: Int) => x * 2

This is a simple (anonymous) Function in Scala

You can assign it to a val and pass it around

val timesTwo = (x: Int) => x * 2
val list = List(1, 2, 3)

list.map(timesTwo)

e.g. pass it to another function! 

Wait, so what is a method then!?

A method generally speaking is a "function" that will produce a value only if you call it by providing required arguments.

def timesTwo(x: Int) = x * 2

timesTwo(2)
//Declaration

//method
scala> def addTwoM(number: Int) = number + 2
addTwo: (number: Int)Int

//function
scala> val addTwoF = (number: Int) => number + 2
addTwo: Int => Int = $$Lambda$1122/339082934@34fe89a5

//Invocation

//method
scala> addTwoM
<console>:13: error: missing argument list for method addTwoM

//function - it has a type! 
scala> addTwoF
res7: Int => Int = $$Lambda$1124/1009062488@3ad142f0

Wait, so what is a method then!? II

Can you pass a method to another function?

Yes! Compiler will convert your method into a function

When should I use function literal vs a method?

Use functions when you want to pass them around and use methods defined on a Function! Use methods for all computations

val list = List(1, 2, 3) 

def timesTwo(n: Int) = n * 2

//works!
list.map(timesTwo)

Higher Order Functions

Higher order functions take other functions as parameters or return a function as a result.

// Better
val filtered = newSalaries.filter(amount => amount < 70000)
// Or even better
val filtered = newSalaries.filter(_ < 70000)
val salaries = List(20000, 70000, 40000)

val salaryCheck = (amount: Int) => amount < 70000
val filtered = newSalaries.filter(salaryCheck)

map

  • Iterates over a data structure while applying supplied function
  • Transformation is applied to all elements  
val salaries = List(20000, 70000, 40000)

val newSalaries = salaries.map(x => x * 2) 

  • Can work with lists, maps, sets and others...
def map(f: (A) ⇒ B): List[B]    


Scala map signature:

flatMap

  • Iterates over a data structure while applying supplied function (simillar to map)
  • Flattens the data structure  
val shoppingBasket = List("Banana", "Apple", "Orange")

def buyOneGetOneFree(el: String): List[String] = {
  List(el, el)
}

val newSalaries = shoppingBasket.flatMap(el => buyOneGetOneFree(el))

//intermediate step before flattening 
//List(List("Banana", "Banana"), List("Apple", "Apple"), List("Orange", "Orange"))

//end result after flattening
//List("Banana", "Banana", "Apple", "Apple", "Orange", "Orange")
def flatMap(f: (A) ⇒ List[B]): List[B]    


Scala flatMap signature:

filter

  • Iterates over a data structure while checking all elements if they satisfy the provided predicate
  • Returns all elements which satisfy the condition
val salaries = List(20000, 70000, 40000)

val richFilter = (amount: Int) => amount < 10000
val filtered = newSalaries.filter(richFilter)
def filter(p: (A) ⇒ Boolean): List[A]

Scala filter signature:

fold

  • Process a data structure recursively and collapses all elements while applying given function
  • Requires an initial value

Scala fold signature:

val salaries: List[Int] = List(20000, 70000, 40000)

val total: Int = newSalaries.fold(0)(_ + _)
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1

fold vs foldLeft, foldRight

  • foldLeft / foldRight iterates over a data structure and collapses all elements while applying given function
  • Requires an initial value and uses an accumulator to "remember" previous iteration/value
def fold[A1 >: A](z: A1)(op: (A1, A1) ⇒ A1): A1
def foldLeft[B](z: B)(op: (B, A) ⇒ B): B
def foldRight[B](z: B)(op: (A, B) ⇒ B): B

Scala fold signatures:

  • foldLeft - traverses from left to right
  • foldRight - traverses from right to left
  • fold - traverses in no particular order, has no accumulator

fold vs foldLeft, foldRight

folding examples

val list: List[Int] = List(1, 3, 5)

val total: Int = inputList.foldLeft(0){(acc, num) => acc + num}
val list: List[Int] = List(1, 3, 5)

val length: Int = list.foldLeft(0){(acc, _) => acc + 1}

Exercise time!

Intro to Scala II

By Povilas Lape

Intro to Scala II

Scala Course Lesson 2

  • 137