KEMBAR78
Demystifying functional programming with Scala | PDF
Scalafunctional programming demystified
@_denisftw_
http://appliedscala.com
Roadmap
1. Introduction
2. Language fundamentals
3. Functional programming
Users
Twitter (Ruby)
Foursquare (Java/.NET)
Tumblr (PHP)
Guardian (Java)
Klout (PHP)
Coursera (PHP)
LinkedIn*
Netflix* (JVM)
History
2003 - Released in EPFL
2008 - ‘Programming in Scala’
2010 - Version 2.8
2011 - Typesafe Inc. founded
2012 - First course on Coursera
2013 - Version 2.10
Recipe
● Take Java-like syntax
● Remove specifics and
unnecessary limitations
● Mix in functional features*
Complexity
● About 40 reserved words
● Only 2 namespaces vs. 4 in Java (fields, methods,
packages, types)
● Methods instead of operators
● No primitives (AnyVal)
Hierarchy
scala
Double
scala
Unit
scala
AnyVal
scala
Any
scala
AnyRef
java.lang
String
scala.collection.immutable
List
scala
Null
scala
Nothing
scala
Int
Collections
s.c
Seq
s.c
Set
scala.collection
Iterable
scala.collection
Traversable
s.c
Map
s.c
List
s.c
Buffer
s.c
IndexedSeq
● Redesigned in 2.8
● 100500+ methods
● Immutable by default
● Easy conversions
● Buffers
Basics
val a = 123
var b: Int = 124
def increment = (a: Int) => a + 1
Basics
val list = new List[Int](1, 2, 3, 4)
val first = list(0)
Classes
class User (var id: Int, val name: String) {
}
Classes
class User (var id: Int, val name: String) {
override def toString = {
id + ". " + name
}
}
scala> new User(1, "Simon")
Objects
object User {
}
Objects
object User {
def apply(id: Int, name: String) =
new User(id, name)
}
scala> User.apply(2, "Bob")
Objects
object User {
def apply(id: Int, name: String) =
new User(id, name)
}
scala> User.apply(2, "Bob")
scala> User(3, "Chris")
Language tricks
val arr = Array[String]("a", "b")
val el = arr(1)
// arr.apply(1)
Language tricks
def abs(a: Int) = if (a >= 0) a else -a
abs(12)
abs{-13}
Language tricks
def greet(implicit name: String) = "Hello" + name
implicit val n = "Joe"
greet
Functional features
● Functional data types
● Tail recursion
● Immutability
● Higher-order functions
● Currying
● Pattern matching
● Lazy evaluation
Functional data types
val l = 1 :: 2 :: 3 :: Nil
// List(1, 2, 3)
l.head // 1
l.tail // List(2, 3)
l.isEmpty // false s.c.i
Nil
s.c.i
::[T]
scala.collection.immutable
List[+T]
Functional data types
val l = 1 :: 2 :: 3 :: Nil
val l2 = 0 :: l
1 2 3 Nil
0
Imperative example
def concat(list: List[Any]): String = {
}
Imperative example
def concat(list: List[Any]): String = {
val iter = list.iterator
var result = ""
while (iter.hasNext) {
result += iter.next
}
result
}
Tail recursion
def concat(l: List[Any]): String =
if (l.isEmpty)
else
Tail recursion
def concat(l: List[Any]): String =
if (l.isEmpty)
""
else
l.head + concat(l.tail)
Tail recursion
def concatT(s: String, list: List[Any]): String =
if (list.isEmpty)
s
else
concatT(s + list.head, list.tail)
Tail recursion
def concat(l: List[Any]): String = {
@tailrec
def concatT(s: String, list: List[Any]): String =
if (list.isEmpty)
s
else
concatT(s + list.head, list.tail)
concatT("", l)
}
Pattern matching
def concat(l: List[Any]): String =
l match {
case Nil =>
case head :: tail =>
}
Pattern matching
def concat(l: List[Any]): String =
l match {
case Nil => ""
case head :: tail =>
head + concat(tail)
}
Lazy evaluation
lazy val now = new Date // 13:52:24
now // 13:55:05
Lazy evaluation
def debug(on: Boolean, msg:=> String) = {
if (on) {
doSomething(msg)
}
}
Lazy evaluation
val numbers = Stream.from(0)
numbers.take(5).toArray
// Array[Int](0, 1, 2, 3, 4)
Higher-order functions
val l = List(1, 2, 3, 4, 5)
l.map(el => el + 1)
// List(2, 3, 4, 5, 6)
Higher-order functions
val l = List(1, 2, 3, 4, 5)
l.filter(el => el % 2 == 0)
// List(2, 4)
Higher-order functions
val l = List(1, 2, 3, 4, 5)
l.foreach{ el => print(el) }
// 12345
Currying
def sum(x: Int)(y: Int) = x + y
sum(4)(5)
Currying
val l = List(1, 2, 3, 4, 5)
list.fold(0) { (a, b) =>
a + b
}
Currying
def tx[A](block: Session => A)
(implicit ctx: Context)
Currying
import scalikejdbc._
val statement = …
DB.tx { session =>
SQL(statement).execute
}
flatMap
class C[T]
def map[R](block: T => R): C[R] = …
def flatMap[R](block: T => C[R]): C[R] = …
flatMap
val l1 = List(1, 2, 3)
val l2 = List("a", "b")
l1.flatMap{ el1 =>
l2.map{ el2 => el1 + el2 }
}
// 1a, 1b, 2a, 2b, 3a, 3b
Monads
A monad is just a monoid
in the category of endofunctors
What's the problem?
for expressions
● map
● flatMap
● filter
● foreach*
for expressions
l1.flatMap { el1 =>
l2.map { el2 => el1 + el2 }
}
for expressions
l1.flatMap { el1 =>
l2.map { el2 => el1 + el2 }
}
for {
el1 <- l1
el2 <- l2
} yield el1 + el2
Stream
val numbers = Stream.from(0)
scala.collection.immutable
Stream[+T]
scala.collection
Traversable[+T]
Stream
val numbers = Stream.from(0)
val even = for {
num <- numbers if num % 2 == 0
} yield num
Option
isDefined: Boolean
get: T
getOrElse[T](default: T): T
scala
None
scala
Some[+T]
scala
Option[+T]
Option
def lookup(login: String, password: String):
Option[User]
val maybeUser: Option[User] = …
Option
maybeUser.map { user =>
user.name
}.map { name =>
"Welcome back," + name
}.getOrElse("Hi")
Option[User]
Option[String]
Option[String]
String
map
map
getOrElse
Option
for {
user <- maybeUser
name <- Some(user.name)
} yield
"Welcome back," + name
Try
def parse(json: Js): String
try {
parse(js)
}
catch {
case e: Exception => …
}
Try
def parse(js: Js): String
val nameT = Try {
parse(js)
}
val maybeName = nameT.toOption
scala.util
Failure[+T]
scala.util
Success[+T]
scala.util
Try[+T]
Try
def parse(js: Js): String
def store(name: String): Int
for {
name <- Try(parse(json))
id <- Try(store(name))
} yield id
scala.util
Failure[+T]
scala.util
Success[+T]
scala.util
Try[+T]
Future
def query(q: String): List[String]
val resF = Future { query(q) }
resF.onSuccess {
case list => …
}
resF.onFailure {
case ex => …
}
scala.concurrent
Future[+T]
Future
def query(q: String): List[String]
def store(l: List[String]): Int
queryF.onSuccess {
case list => {
val storeF = Future { store(list) }
storeF.onSuccess { case id => … }
}
}
scala.concurrent
Future[+T]
Future
val resultsF = Future{ query("WTF") }
for {
results <- resultsF
id <- Future{ store(results) }
} yield id
scala.concurrent
Future[+T]
Wait... there’s more!
● object-oriented programming
● arcane things
● actors
● ecosystem
● tools and frameworks
The book
● Suited for people with no prior
experience in Scala
● Includes functional programming tutorial
● Focuses on Play 2.5
● ScalikeJDBC, MacWire, Akka
● Webpack, Sass, React, EcmaScript 6
Questions?

Demystifying functional programming with Scala