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!
Feedback link -https://goo.gl/forms/k65F4nDTMsAFHOr12
Intro to Scala II
By Povilas Lape
Intro to Scala II
Scala Course Lesson 2
- 137