Slides: http://arild.github.io/scala-workshop
Code: https://github.com/arild/scala-workshop
Arild Nilsen
Sjur Millidahl
October, 2013
Functional programming is programming without assignment statements.
Robert C. Martin (Uncle Bob), January 2013
Named functions
def createList(param1: Int, param2: Int): List[Int] = {
val myImmutableList = List(param1, param2)
myImmutableList
}
Anonymous functions
(x: Int) => x + 1
Can be accepted as a parameter
def myMethod(n: Int, f: Int => Boolean) = f(n)
scala> 4 :: List(1, 2, 3) // Prepend, O(1)
res0: List[Int] = List(4, 1, 2, 3)
scala> List(1, 2, 3) ::: List(4) // Append, O(n), prefer prepend
res1: List[Int] = List(1, 2, 3, 4)
scala> val numbers = List(1,2,3)
numbers: List[Int] = List(1, 2, 3)
scala> numbers.map((x: Int) => x + 1)
res0: List[Int] = List(2, 3, 4)
scala> val myList = List(1,2,3,4,5,6)
myList: List[Int] = List(1, 2, 3, 4, 5, 6)
scala> myList.filter((x: Int) => x > 3)
res0: List[Int] = List(4, 5, 6)
//Adds an element at the beginning of this list
def ::(x: A): List[A]
//Adds the elements of a given list in front of this list
def :::(prefix: List[A]): List[A]
//Selects the first element of this list
def head: A
//Selects last n elements
def takeRight(n: Int): List[A]
//Selects all elements of this list which satisfy a predicate
def filter(p: (A) ⇒ Boolean): List[A]
match on any sort of data with a first-match policy.
def toYesOrNo(choice: Int): String = choice match {
case 1 => "yes"
case 0 => "no"
case _ => "error"
}
def f(x: Any): String = x match {
case i:Int => "integer: " + i
case _:Double => "a double"
case s:String => "I want to say " + s
}
A Future is a read-handle to a single value (read-many) that may be available within a specific time-frame
A Promise is a write-handle to a single value (write-once) that should be made available within a specific time-frame
println("Test print before future")
val s = "hello"
val f = future {
Thread.sleep(10)
s + " future!"
}
println("Test print after future")
// Completely asynchronous
f.onSuccess { case s => println(s) }
// Blocks until the future is ready
Await.ready(f, Duration.Inf)
Test print before future
Test print after future
hello future!
//Asynchronously processes the value in
//the future once the value becomes available.
def foreach[U](f: T => U): Unit
//Creates a new future by applying a function to the successful
//result of this future.
def map[S](f: T => S): Future[S]
//Creates a new future by applying a function to the successful
//result of this future, and returns the result of the function
//as the new future.
def flatMap[S](f: T => Future[S]): Future[S]
//Creates a new future by filtering the value of the current future
//with a predicate.
def filter(p: T => Boolean): Future[T]
val riskyRes = future { riskyWork() }
val safeRes = future { safeWork() }
val finalRes = riskyRes recoverWith {
case e: IllegalArgumentException => safeRes
}
val keys = future { readFile("keys.txt") }
val values = future { readFile("values.txt") }
val data = keys.zip(values)
val hashMap = data.map((ls: (List[String], List[String])) => {
ls._1.zip(ls._2).toMap
})
hashMap.recover {
case e: FileNotFoundException => {
Map[String, String]()
}
}.onSuccess {
case map => {
println(map)
}
}
Await.result(hashMap, Duration.Inf)
val p = promise[T]
val f = p.future
val producer = future {
val result = produceSomething()
p success result
continueDoingSomethingUnrelated()
}
val consumer = future {
startDoingSomething()
f onSuccess {
case res => doSomething(res)
}
}