8. Mutability?scala> val x = mutable.HashMap[String,String]()
x: scala.collection.mutable.HashMap[String,String] = Map()
scala> x += ("a" "a")→
res0: x.type = Map(a -> a)
------
scala> val y = immutable.HashMap[String,String]()
y: scala.collection.immutable.HashMap[String,String] = Map()
scala> y += ("a" "a")→
<console>:9: error: reassignment to val
y += ("a" "a")→
9. Free of side effects
• Code reuse
• Make better building blocks
• Easier to reason about, optimize and test
10. Functions are First-classdef multiplyFour : Int Int = (4 * )⇒
def addTwo: Int Int = (2 + )⇒
def º[A,B,C](f:A B, g : B C ) = f andThen g // Parametric-⇒ ⇒
polymorphism
def f = º(multiplyFour , addTwo) // We’ll make it look more ‘natural’
in the section: Typeclasses
f(4)
res6: Int = 18
(addTwo compose multiplyFour)(4)
res4: Int = 18
11. Closure
val x = 3 // what if its `var x = 3`?
def = (y: Int) x + yλ ⇒
Be careful what you `close` over i.e. context-
sensitive
val xval x λλ33
var xvar x λλ33
77
12. Lambdas
def g( : Int Int) =λ ⇒ λ
g((x:Int) x * 2)⇒ OK
g( (x:Int) (y:Int) x + y )⇒ ⇒ FAIL
g( ((x: Int) (y: Int) x + y)(4) )⇒ ⇒ OK
13. Matching
// simulate a binary tree
sealed trait Tree
case class Branch(ele: Int, left:Tree: right:Tree) extends Tree
case object Leaf extends Tree
// inOrder aka Depth-First Traversal
def inOrder(t:Tree) : List[Int] = t match {
case Branch(ele, l, r) inOrder(l):::List(ele):::inOrder(r)⇒
case Leaf Nil⇒
}
14. Recursion
def string2spaces(ss: List[Char]) = ss match {
case Nil Nil⇒
case h :: tail ‘ ‘ :: string2spaces(tail)⇒
}
import scala.annotation.tailrec
@tailrec
def string2spaces(ss: List[Char], acc: List[Char]): List[Char] = ss match {
case Nil acc⇒
case h :: tail string2spaces(tail,‘ ‘ +: acc)⇒
}
15. Lazy vs Eager Eval
def IamEager[A](value:A)
def IamLazy[A](value: ⇒ A)
16. TypeclassesWhat I really want to write is
(addTwo ∘ multiplyFour)(4) and not
(addTwo compose multiplyFour)(4)
typeclasses - create higher kinded types! e.g.
List[Int Int]⇒
17. Typeclasses in Scala
trait Fn extends (Int Int) {⇒
def apply(x: Int) : Int
def º(f: Fn) = f andThen this
}
def addTwo = new Fn { def apply(x: Int) = 2 + x }
def multiplyFour = new Fn { def apply(x: Int) = 4 * x }
multiplyFour º addTwo
res0: Int => Int = <function1>
(addTwo º multiplyFour)(4)
res1: Int = 18
18. Typeclasses in Scala
sealed trait MList[+A]
case object Nil extends MList[Nothing]
case class ::[+A](head:A, tail: MList[A]) extends
MList[A]
object MList {
def apply[A](xs:A*) : MList[A] = if (xs.isEmpty) Nil
else ::(xs.head, apply(xs.tail: _*))
}
19. Typeclasses in Scala
object Main extends App {
val x = MList(1,2,3,4,5) match {
case ::(x, ::(2, ::(4, _))) => x
case Nil => 42
case ::(x, ::(y, ::(3, ::(4, _)))) => x + y
case ::(h, t) => h
case _ => 101
}
println(s"value of ${x}")
}
20. Adhoc Polymorphism
scala> (1,2,3) map { 1 + _ }
<console>:8: error: value map is not a member of (Int,
Int, Int)
(1,2,3) map { 1 + _ }
scala> implicit def giveMeMap[A](t : Tuple3[A,A,A]) =
new Tuple3[A,A,A](t._1, t._2, t._3) {
def map[B](f: A => B) = new Tuple3(f(_1), f(_2), f(_3))
}
scala> (1,2,3) map { 1 + _ }res1: (Int, Int, Int) = (2,3,4)
21. Adhoc Concurrency
class Matrix(val repr:Array[Array[Double]])
trait ThreadStrategy {
def execute[A](f: () A) : () A⇒ ⇒
}
object SingleThreadStrategy extends ThreadStrategy { //
uses a single thread }
object ThreadPoolStrategy extends ThreadStrategy { //
uses a thread pool }
22. Adhoc Concurrency
scala> val m = new Matrix(Array(Array(1.2, 2.2),Array(3.4, 4.5)))
m: Matrix =
Matrix
|1.2 | 2.2|
|3.4 | 4.5|
scala> val n = new Matrix(Array(Array(1.2, 2.2),Array(3.4, 4.5)))
n: Matrix =
Matrix
|1.2 | 2.2|
|3.4 | 4.5|
23. Adhoc Concurrency
scala> MatrixUtils.multiply(m, n)
res1: Matrix =
Matrix
|8.92 | 12.540000000000001|
|19.38 | 27.73|
scala> MatrixUtils.multiply(m, n)(ThreadPoolStrategy)
Executing function on thread: 38
Executing function on thread: 39
Executing function on thread: 40
Executing function on thread: 41
25. Functional Data
Structures - List
def foldRight[A,B](l: List[A], z: B)(f: (A,B) B) : B = l match {⇒
case Nil z⇒
case ::(h, t) f(h, foldRight(t,z)(f))⇒
}
@tailrec
def foldLeft[A,B](l: List[A], z: B)(f: (B,A) B) : B = l match {⇒
case Nil z⇒
case ::(h, t) => foldLeft(t, f(z,h))(f)
}
27. If i had more time...
• Existential Types
• Self Types
• Structural Typing (think Duck Typing)
• Compile-time metaprogramming
(macros,quasiquotes)
• Reactive Programming through Akka
• Monoids, Monads, Endos, Corecursive and a
whole lot more