SlideShare a Scribd company logo
Whereobjects and functionsmeetby Mario Fuscomario.fusco@gmail.comtwitter: @mariofusco
day 1:    hour 1: Object Orientation        Classes, Objects and Traits        Generic Types        Case Classes, Patter Matching and Tuples    hour 2: Functional Programming        First-class and Anonymous Functions Higer-Order Functions and Curry        Implicit Parameters and Conversions        Using Scala features to create a simple DSLday 2:    hour 1: Using OO and FP together        Structural Typing        Scala Collections        For-Comprehensions        Options and Monads    hour 2: Concurrency        Abstractions for Concurrency        Actors and Remote Actors
Do we need a new language?Keep It SimpleVs.Do More With Less
statically typedobject-orientedfunctionalscriptableWhy Scala?conciseJava compatibleextensibleconcurrent
The first Scala classclass Rational(n: Int, d: Int) {valnum = nval den = ddefthis(n: Int) = this(n, 1)def + (that: Rational): Rational =new Rational(num * that.den + that.num * den, den * that.den)def + (i: Int): Rational = new Rational(num + i * den, den)overridedeftoString = "" + num + "/" + den}
Named and default parametersclassRational(n: Int= 1, d: Int = 1) extendsAnyRef { ....}Rational(n = 2, d = 3)Rational(d = 3, n = 2)Rational(d = 3)Rational()
Scala’s type hierarchy
Object(Companion)objectRationalOneextends Rational(1)object Rational {def apply(n: Int) = new Rational(n)def apply(n: Int, d: Int) = new Rational(n, d)}valone = RationalOnevaltwo = Rational(1) + one val two = Rational(1).+(one)
TraitsclassAnimal                  { defeat(): Unit }traitMammalextendsAnimal   { defgiveBirth(): Mammal }traitHasWingsextendsAnimal { deffly(): Unit }traitHasLegsextendsAnimal  { defwalk(): Unit }class Snake extendsAnimalclassFrogextendsAnimal with HasLegsclassCatextendsAnimalwithMammalwithHasLegsclassBatextendsAnimalwithMammalwithHasWingsclass Chimera extendsAnimalwithMammalwithHasWingswithHasLegs
Let’s put alltogethertrait IntSet {defcontains(x: Int): BooleandefnotContains(x: A) = !contains(x)defadd(x: Int): IntSet}object EmptySetextends IntSet {defcontains(x: Int): Boolean = falsedefadd(x: Int): IntSet = new NonEmptySet(x, EmptySet, EmptySet)}class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet{defcontains(x: Int): Boolean =    if (x < elem) left contains x    else if (x > elem) right contains x    else truedefadd(x: Int): IntSet =    if (x < elem) new NonEmptySet(elem, left add x, right)    else if (x > elem) new NonEmptySet(elem, left, right add x)    else this}
GenericTypestrait Set[A <: Ordered[A]] {def contains(x: A): Booleandef add(x: A): Set[A]}classEmptySet[A <: Ordered[A]] extends Set[A] {def contains(x: A): Boolean = falsedef add(x: A): Set[A] =    new NonEmptySet(x, newEmptySet[A], newEmptySet[A])}classNonEmptySet[A <: Ordered[A]]                (elem: A, left: Set[A], right: Set[A]) extends Set[A] {def contains(x: A): Boolean =if (x < elem) left contains xelse if (x > elem) right contains xelsetruedef add(x: A): Set[A] =if (x < elem) newNonEmptySet(elem, left add x, right)elseif (x > elem) newNonEmptySet(elem, left, right add x)elsethis}
Case classessealed traitExprcase class Var(name: String) extendsExprcase class Number(num: Double) extendsExprcase class Unop(op: String, arg: Expr) extendsExprcase class Binop(op: String, l: Expr, r: Expr) extendsExpr
Pattern matchingdef simplify(expr: Expr): Expr = exprmatch {caseUnop("-", Unop("-", e)) => e   // Double negationcaseBinop("+", e, Number(0)) => e  // Adding zerocaseBinop("*", e, Number(1)) => e  // Multiplying by onecase _ => expr}// Simplify double negation: simplified = Var("x")val simplified = simplify(Unop("-", Unop("-", Var("x"))))
Tuplesvalpair = (2, "items")println(pair._1) // prints 2println(pair._2) // printsitemsdefdivmod(x: Int, y: Int): (Int, Int) = (x / y, x % y)divmod(x, y) match {case (n, d) => println("quotient: " + n + ", rest: " + d)}
defsumInts(a: Int, b: Int): Int = if (a > b) 0 else a + sumInts(a + 1, b)defsumSquares(a: Int, b: Int): Int=  if (a > b) 0 else a * a + sumSquares(a + 1, b)First-Class Functiondefsum(f: Int => Int, a: Int, b: Int): Int=  if (a > b) 0 else f(a) + sum(f, a + 1, b)defid(x: Int): Int = xdefsumInts(a: Int, b: Int): Int = sum(id, a, b)defsquare(x: Int): Int = x * xdefsumSquares(a: Int, b: Int): Int = sum(square, a, b)Anonymous FunctiondefsumInts(a: Int, b: Int): Int = sum((x: Int) => x, a, b)defsumSquares(a: Int, b: Int): Int = sum((x: Int) => x * x, a, b)
Higher-Order Functions and Currydefsum(f: Int => Int): (Int, Int) => Int = {defsumF(a: Int, b: Int): Int= if(a > b) 0 else f(a) + sumF(a + 1, b)sumF}defsumInts = sum(x => x)defsumSquares= sum(x => x * x)val sum1To10 = sumInts(1, 10)valsum1To10 = sum(x => x)(1, 10)def sum(f: Int => Int)(a: Int, b: Int): Int=if (a > b) 0 else f(a) + sum(f)(a + 1, b)def sum(a: Int, b: Int)(f: Int => Int): Int = if(a > b) 0 else f(a) + sum(a + 1, b)(f)valsum1To10 = sum(1, 10) {  x => x }
ImplicitparametersabstractclassAggregator[A] {defunit: Adefadd(x: A, y: A): A}objectstringAggregatorextendsAggregator[String] {defunit= ""defadd(x: String, y: String): String = x concaty}objectintAggregatorextendsAggregator[Int] {defunit= 0defadd(x: Int, y: Int): Int= x + y}def sum[A](l: List[A]) (a: Aggregator[A]): A =if (l.isEmpty) a.unitelsea.add(l.head, sum(l.tail)(a))sum(List("a", "b", "c"))(stringAggregator)sum(List(1, 2, 3))(intAggregator)(implicit a: Aggregator[A]): A =
Implicitconversionval a = new Rational(2, 3)val b = a + 2     // = 8/3val c = 2 + a     // Compilation ErrorimplicitdefintToRational(x: Int) = newRational(x)valc = 2 + a      // = 8/3ViewboundtraitSet[A <% Rational]
Duck typing is the dynamic mechanism that allows to discover a dog cannot say quack only at runtime... in production... on friday eveningStructural Typing(duck typing done right)doQuack(d) { d.quack() }defdoQuack(d:{ def quack():Unit }) =d.quack()classDuck { quack() { println "quack" } }doQuack(new Duck)classDuck { defquack() = println "quack" }doQuack(new Duck)class Dog { barf() { println "barf" } }doQuack(new Dog)class Dog { defbarf() = println "barf" }doQuack(new Dog)compilationerrorruntime error
Listsvalletters: List[String] = List("a", "b", "c", "d")valemptyList = Nilvalletters= "a" :: "b" :: "c" :: "d" :: Nilx :: ysisequivalent to  ys.::(x) // infix operator == right associativexs ::: ysisequivalent toys.:::(xs)letters.head = "a"letters.tail = List("b", "c", "d")defsortedInsert(x: Int, xs: List[Int]): List[Int] = xsmatch {case List() => List(x)case y :: ys => if (x <= y) x :: xselse y :: sortedInsert(x, ys)}
Higher-Order Functions on Listsvalanimals = List("dog", "cat", "horse", "rabbit")animals.foreach(s => println(s))defforeach(f: A => Unit) {thismatch {caseNil => ()case x :: xs => f(x); xs.foreach(f)  }}animals.foreach(println_)animals.foreach(println)animals.map(s => s + "s")animals.mkString(", ")animals.count(s => s.length > 3)animals.remove(s => s.length > 3)animals.sort((s,t) => s.charAt(1) < t.charAt(1))animals.foldLeft(0)((s,t) => s + t.length)(0 /: animals)(_ + _.length)
For-Comprehensionsfor (p <- personsifp.age > 20) yield p.namepersonsfilter (p => p.age > 20) map (p => p.name)for {  p <- persons			// Generators  c <- p.childrenif c.name startsWith"A" 	// Filter} yield p.name			// Map
Given n>0 findallpairs iand j where 1 ≤j ≤ i ≤ n and i+jis primeList.range(1, n)  .map(i => List.range(1, i).map(x => (i, x)))  .foldRight(List[(Int, Int)]()) {(xs, ys) => xs ::: ys}  .filter(pair => isPrime(pair._1 + pair._2))List.range(1, n)  .flatMap(i => List.range(1, i).map(x => (i, x)))  .filter(pair => isPrime(pair._1 + pair._2))Where: class List[A] { defflatMap[B](f: A => List[B]): List[B] }for { i <- List.range(1, n)      j <- List.range(1, i)      if isPrime(i + j) } yield {i, j}List.range(1, n)  .flatMap(i =>List.range(1, i)       .filter(j => isPrime(i+j))       .map(j => (i, j)))
Tony Hoare, who invented the null reference in 1965 while working on an object oriented language called ALGOL W, called its invention his “billion dollar mistake”Optionsvalcapitals = Map("Italy" -> "Rome", "Switzerland" -> "Bern",                    "Germany" -> "Berlin" , "France" -> "Paris")println(capitals.get("Italy"))  // Some(Rome)println(capitals.get("Spain"))  // Noneprintln(capitals.get("Italy").get)  // Romeprintln(capitals.get("Spain").get)  // thorwsExceptionprintln(capitals.get("Spain").getOrElse("Unknown"))  // Unknown
OptionsasMonadsdefmap[B](f: A => B): M[B]defflatMap[B](f: A => M[B]): M[B]deffilter(p: A => Boolean): M[A]defreadPositiveIntParam(params: Map[String, String], name: String): Int= paramsgetnameflatMapstringToIntfilter (_ > 0) getOrElse 0defstringToInt(string: String) : Option[Int] = try {  Some(string.toInt)} catch {  case _ : java.lang.NumberFormatException => None}defreadPositiveIntParam(params: Map[String, String], name: String): Int =  (for{ param<- paramsgetname; value<- stringToInt(param) if (value > 0)  } yieldvalue) getOrElse 0valparams = Map("a" -> "5", "b" -> "false", "c" -> "-3")valreadPositiveIntParam(params, "a") // == 5valreadPositiveIntParam(params, "b") // == 0 – Samefor "c" and "d"
Signals and Monitorsdefsynchronized[A] (e: => A): Adefwait()defwait(msec: Long)defnotify()defnotifyAll()SyncVarclass SyncVar[A] {  private var isDefined: Boolean = false  private varvalue: A = _defget = synchronized {    while (!isDefined) wait()    value  }defset(x: A) = synchronized {    value = x; isDefined = true; notifyAll()  }defisSet: Boolean = synchronized { isDefined }defunset = synchronized { isDefined= false }}
Futuresdeffuture[A](p: => A): Unit => A = {valresult = new SyncVar[A]  fork { result.set(p) }  (() => result.get)}valx = future(someLengthyComputation)anotherLengthyComputationvaly = f(x()) + g(x())Semaphoresclass Lock {varavailable = truedefacquire = synchronized {    while (!available) wait()    available = false  }defrelease = synchronized {    available = true    notify()  }}Mailboxesclass MailBox {defsend(msg: Any)defreceive[A](f: PartialFunction[Any, A]): AdefreceiveWithin[A](msec: Long)(f: PartialFunction[Any, A]): A}
ActorsclassPrinterActorextendsActor {defact() {while(true) {  receive {casemsg=> println("Received message: " + msg)      }    } }}valprinterActor = newPrinterActorprinterActor.startprinterActor! "hi there“  // prints "Received message: hi there"printerActor ! 23          // prints "Received message: 23"
Creating Actors with the actormethodimportscala.actors.Actor._valprinterActor = actor {while(true) {    receive {case s: String => println("I got a String: " + s)case i: Int => println("I got an Int: " + i.toString)case _ => println(" I don’t know what I got ")    }  }}printerActor ! "hi there"  // prints “I got a String: hi there”printerActor ! 23          // prints “I got an Int: 23”printerActor ! 3.33        // prints “I don’t know what I got”
reactinstead of receive (whenpossible)importscala.actors.Actor._valprinterActor = actor {  loop {react {case s: String => println("I got a String: " + s)case i: Int => {println("I got an Int: " + i.toString)println(“Waiting for another Int")react {case j: Int=> println(“Another Int: " + j.toString)       }     }case _ => exit    }  }}
Message types! send an asynchronous message which means that the sending actor does not wait until the message is received; its execution continues immediately. All actors have a mailbox which buffers incoming messages until they are processed!? senda synchronous message: causes the sending actor to wait until a response is received which is then returned. There is an overloaded variant taking a timeout and returning an Option[Any] instead of Any!! similar to !? In the sensethatitallows to get an answer from the receiver. However, instead of blocking the sending actor until a response is received, it returns Future instance that can be used to retrieve the receiver’s response once it is available
Remote Actorsactor { // SERVER ACTORRemoteActor.classLoader = getClass().getClassLoader()  alive(9000) // starts remote actor listening on the given port  register('Server, self) // registers the actor using the symbolloop {receive {case Message => sender ! ... }  }} actor { // CLIENT ACTORtrapExit= true         // listens exit of linked actorsRemoteActor.classLoader= getClass().getClassLoader()alive(9001)valserver = select(Node("127.0.0.1", 9000), 'Server) link(server)           // linksthisactor to the server one server ! Message       // sends a Message to the server}

More Related Content

PPTX
Java 7, 8 & 9 - Moving the language forward
PDF
FP in Java - Project Lambda and beyond
PDF
Hammurabi
PDF
From object oriented to functional domain modeling
PDF
Java 8 Workshop
PDF
OOP and FP - Become a Better Programmer
PPTX
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
PDF
Atomically { Delete Your Actors }
Java 7, 8 & 9 - Moving the language forward
FP in Java - Project Lambda and beyond
Hammurabi
From object oriented to functional domain modeling
Java 8 Workshop
OOP and FP - Become a Better Programmer
Concurrency, Scalability & Fault-tolerance 2.0 with Akka Actors & STM
Atomically { Delete Your Actors }

What's hot (20)

PDF
Sneaking inside Kotlin features
PDF
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
PDF
Demystifying functional programming with Scala
PDF
Idiomatic Kotlin
PDF
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
PPTX
Joy of scala
PDF
Pragmatic Real-World Scala (short version)
PDF
Let's make a contract: the art of designing a Java API
PDF
Kotlin, why?
PDF
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
PDF
The Death of Final Tagless
PDF
One Monad to Rule Them All
PDF
Futures e abstração - QCon São Paulo 2015
PDF
Scalaz 8 vs Akka Actors
PDF
Comparing JVM languages
PPSX
What's New In C# 7
PDF
Scala is java8.next()
PDF
MTL Versus Free
PPT
Functional Programming In Java
Sneaking inside Kotlin features
The Easy-Peasy-Lemon-Squeezy, Statically-Typed, Purely Functional Programming...
Demystifying functional programming with Scala
Idiomatic Kotlin
Map(), flatmap() and reduce() are your new best friends: simpler collections,...
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
Joy of scala
Pragmatic Real-World Scala (short version)
Let's make a contract: the art of designing a Java API
Kotlin, why?
"Немного о функциональном программирование в JavaScript" Алексей Коваленко
The Death of Final Tagless
One Monad to Rule Them All
Futures e abstração - QCon São Paulo 2015
Scalaz 8 vs Akka Actors
Comparing JVM languages
What's New In C# 7
Scala is java8.next()
MTL Versus Free
Functional Programming In Java
Ad

Viewers also liked (12)

PDF
If You Think You Can Stay Away from Functional Programming, You Are Wrong
PDF
Laziness, trampolines, monoids and other functional amenities: this is not yo...
PDF
Reactive Programming for a demanding world: building event-driven and respons...
PDF
Comparing different concurrency models on the JVM
PDF
Monadic Java
ODP
Drools 6 deep dive
PDF
Why we cannot ignore Functional Programming
PPTX
Real world DSL - making technical and business people speaking the same language
PDF
Seven Deadly Sins
PPT
Swiss army knife Spring
PDF
Introducing Drools
PDF
No more loops with lambdaj
If You Think You Can Stay Away from Functional Programming, You Are Wrong
Laziness, trampolines, monoids and other functional amenities: this is not yo...
Reactive Programming for a demanding world: building event-driven and respons...
Comparing different concurrency models on the JVM
Monadic Java
Drools 6 deep dive
Why we cannot ignore Functional Programming
Real world DSL - making technical and business people speaking the same language
Seven Deadly Sins
Swiss army knife Spring
Introducing Drools
No more loops with lambdaj
Ad

Similar to Scala - where objects and functions meet (20)

PPT
JBUG 11 - Scala For Java Programmers
PPT
SDC - Einführung in Scala
ODP
Scala introduction
PPT
Scala presentation by Aleksandar Prokopec
PPTX
Practically Functional
PPTX
Scala en
PPTX
Scala: Devnology - Learn A Language Scala
ODP
2.1 Recap From Day One
PDF
PDF
Type classes 101 - classification beyond inheritance
PPTX
A Brief Intro to Scala
PDF
Scala or functional programming from a python developer's perspective
PPT
Scala for Java Developers
PDF
Generic Functional Programming with Type Classes
PDF
Going bananas with recursion schemes for fixed point data types
PDF
Oh, All the things you'll traverse
PDF
여자개발자모임터 6주년 개발 세미나 - Scala Language
PPT
Functional programming in scala
PPTX
Qcon2011 functions rockpresentation_scala
PDF
“Going bananas with recursion schemes for fixed point data types”
JBUG 11 - Scala For Java Programmers
SDC - Einführung in Scala
Scala introduction
Scala presentation by Aleksandar Prokopec
Practically Functional
Scala en
Scala: Devnology - Learn A Language Scala
2.1 Recap From Day One
Type classes 101 - classification beyond inheritance
A Brief Intro to Scala
Scala or functional programming from a python developer's perspective
Scala for Java Developers
Generic Functional Programming with Type Classes
Going bananas with recursion schemes for fixed point data types
Oh, All the things you'll traverse
여자개발자모임터 6주년 개발 세미나 - Scala Language
Functional programming in scala
Qcon2011 functions rockpresentation_scala
“Going bananas with recursion schemes for fixed point data types”

Scala - where objects and functions meet

  • 2. day 1:    hour 1: Object Orientation        Classes, Objects and Traits        Generic Types        Case Classes, Patter Matching and Tuples    hour 2: Functional Programming        First-class and Anonymous Functions Higer-Order Functions and Curry        Implicit Parameters and Conversions        Using Scala features to create a simple DSLday 2:    hour 1: Using OO and FP together        Structural Typing        Scala Collections        For-Comprehensions        Options and Monads    hour 2: Concurrency        Abstractions for Concurrency        Actors and Remote Actors
  • 3. Do we need a new language?Keep It SimpleVs.Do More With Less
  • 5. The first Scala classclass Rational(n: Int, d: Int) {valnum = nval den = ddefthis(n: Int) = this(n, 1)def + (that: Rational): Rational =new Rational(num * that.den + that.num * den, den * that.den)def + (i: Int): Rational = new Rational(num + i * den, den)overridedeftoString = "" + num + "/" + den}
  • 6. Named and default parametersclassRational(n: Int= 1, d: Int = 1) extendsAnyRef { ....}Rational(n = 2, d = 3)Rational(d = 3, n = 2)Rational(d = 3)Rational()
  • 8. Object(Companion)objectRationalOneextends Rational(1)object Rational {def apply(n: Int) = new Rational(n)def apply(n: Int, d: Int) = new Rational(n, d)}valone = RationalOnevaltwo = Rational(1) + one val two = Rational(1).+(one)
  • 9. TraitsclassAnimal { defeat(): Unit }traitMammalextendsAnimal { defgiveBirth(): Mammal }traitHasWingsextendsAnimal { deffly(): Unit }traitHasLegsextendsAnimal { defwalk(): Unit }class Snake extendsAnimalclassFrogextendsAnimal with HasLegsclassCatextendsAnimalwithMammalwithHasLegsclassBatextendsAnimalwithMammalwithHasWingsclass Chimera extendsAnimalwithMammalwithHasWingswithHasLegs
  • 10. Let’s put alltogethertrait IntSet {defcontains(x: Int): BooleandefnotContains(x: A) = !contains(x)defadd(x: Int): IntSet}object EmptySetextends IntSet {defcontains(x: Int): Boolean = falsedefadd(x: Int): IntSet = new NonEmptySet(x, EmptySet, EmptySet)}class NonEmptySet(elem: Int, left: IntSet, right: IntSet) extends IntSet{defcontains(x: Int): Boolean = if (x < elem) left contains x else if (x > elem) right contains x else truedefadd(x: Int): IntSet = if (x < elem) new NonEmptySet(elem, left add x, right) else if (x > elem) new NonEmptySet(elem, left, right add x) else this}
  • 11. GenericTypestrait Set[A <: Ordered[A]] {def contains(x: A): Booleandef add(x: A): Set[A]}classEmptySet[A <: Ordered[A]] extends Set[A] {def contains(x: A): Boolean = falsedef add(x: A): Set[A] = new NonEmptySet(x, newEmptySet[A], newEmptySet[A])}classNonEmptySet[A <: Ordered[A]] (elem: A, left: Set[A], right: Set[A]) extends Set[A] {def contains(x: A): Boolean =if (x < elem) left contains xelse if (x > elem) right contains xelsetruedef add(x: A): Set[A] =if (x < elem) newNonEmptySet(elem, left add x, right)elseif (x > elem) newNonEmptySet(elem, left, right add x)elsethis}
  • 12. Case classessealed traitExprcase class Var(name: String) extendsExprcase class Number(num: Double) extendsExprcase class Unop(op: String, arg: Expr) extendsExprcase class Binop(op: String, l: Expr, r: Expr) extendsExpr
  • 13. Pattern matchingdef simplify(expr: Expr): Expr = exprmatch {caseUnop("-", Unop("-", e)) => e // Double negationcaseBinop("+", e, Number(0)) => e // Adding zerocaseBinop("*", e, Number(1)) => e // Multiplying by onecase _ => expr}// Simplify double negation: simplified = Var("x")val simplified = simplify(Unop("-", Unop("-", Var("x"))))
  • 14. Tuplesvalpair = (2, "items")println(pair._1) // prints 2println(pair._2) // printsitemsdefdivmod(x: Int, y: Int): (Int, Int) = (x / y, x % y)divmod(x, y) match {case (n, d) => println("quotient: " + n + ", rest: " + d)}
  • 15. defsumInts(a: Int, b: Int): Int = if (a > b) 0 else a + sumInts(a + 1, b)defsumSquares(a: Int, b: Int): Int= if (a > b) 0 else a * a + sumSquares(a + 1, b)First-Class Functiondefsum(f: Int => Int, a: Int, b: Int): Int= if (a > b) 0 else f(a) + sum(f, a + 1, b)defid(x: Int): Int = xdefsumInts(a: Int, b: Int): Int = sum(id, a, b)defsquare(x: Int): Int = x * xdefsumSquares(a: Int, b: Int): Int = sum(square, a, b)Anonymous FunctiondefsumInts(a: Int, b: Int): Int = sum((x: Int) => x, a, b)defsumSquares(a: Int, b: Int): Int = sum((x: Int) => x * x, a, b)
  • 16. Higher-Order Functions and Currydefsum(f: Int => Int): (Int, Int) => Int = {defsumF(a: Int, b: Int): Int= if(a > b) 0 else f(a) + sumF(a + 1, b)sumF}defsumInts = sum(x => x)defsumSquares= sum(x => x * x)val sum1To10 = sumInts(1, 10)valsum1To10 = sum(x => x)(1, 10)def sum(f: Int => Int)(a: Int, b: Int): Int=if (a > b) 0 else f(a) + sum(f)(a + 1, b)def sum(a: Int, b: Int)(f: Int => Int): Int = if(a > b) 0 else f(a) + sum(a + 1, b)(f)valsum1To10 = sum(1, 10) { x => x }
  • 17. ImplicitparametersabstractclassAggregator[A] {defunit: Adefadd(x: A, y: A): A}objectstringAggregatorextendsAggregator[String] {defunit= ""defadd(x: String, y: String): String = x concaty}objectintAggregatorextendsAggregator[Int] {defunit= 0defadd(x: Int, y: Int): Int= x + y}def sum[A](l: List[A]) (a: Aggregator[A]): A =if (l.isEmpty) a.unitelsea.add(l.head, sum(l.tail)(a))sum(List("a", "b", "c"))(stringAggregator)sum(List(1, 2, 3))(intAggregator)(implicit a: Aggregator[A]): A =
  • 18. Implicitconversionval a = new Rational(2, 3)val b = a + 2 // = 8/3val c = 2 + a // Compilation ErrorimplicitdefintToRational(x: Int) = newRational(x)valc = 2 + a // = 8/3ViewboundtraitSet[A <% Rational]
  • 19. Duck typing is the dynamic mechanism that allows to discover a dog cannot say quack only at runtime... in production... on friday eveningStructural Typing(duck typing done right)doQuack(d) { d.quack() }defdoQuack(d:{ def quack():Unit }) =d.quack()classDuck { quack() { println "quack" } }doQuack(new Duck)classDuck { defquack() = println "quack" }doQuack(new Duck)class Dog { barf() { println "barf" } }doQuack(new Dog)class Dog { defbarf() = println "barf" }doQuack(new Dog)compilationerrorruntime error
  • 20. Listsvalletters: List[String] = List("a", "b", "c", "d")valemptyList = Nilvalletters= "a" :: "b" :: "c" :: "d" :: Nilx :: ysisequivalent to ys.::(x) // infix operator == right associativexs ::: ysisequivalent toys.:::(xs)letters.head = "a"letters.tail = List("b", "c", "d")defsortedInsert(x: Int, xs: List[Int]): List[Int] = xsmatch {case List() => List(x)case y :: ys => if (x <= y) x :: xselse y :: sortedInsert(x, ys)}
  • 21. Higher-Order Functions on Listsvalanimals = List("dog", "cat", "horse", "rabbit")animals.foreach(s => println(s))defforeach(f: A => Unit) {thismatch {caseNil => ()case x :: xs => f(x); xs.foreach(f) }}animals.foreach(println_)animals.foreach(println)animals.map(s => s + "s")animals.mkString(", ")animals.count(s => s.length > 3)animals.remove(s => s.length > 3)animals.sort((s,t) => s.charAt(1) < t.charAt(1))animals.foldLeft(0)((s,t) => s + t.length)(0 /: animals)(_ + _.length)
  • 22. For-Comprehensionsfor (p <- personsifp.age > 20) yield p.namepersonsfilter (p => p.age > 20) map (p => p.name)for { p <- persons // Generators c <- p.childrenif c.name startsWith"A" // Filter} yield p.name // Map
  • 23. Given n>0 findallpairs iand j where 1 ≤j ≤ i ≤ n and i+jis primeList.range(1, n) .map(i => List.range(1, i).map(x => (i, x))) .foldRight(List[(Int, Int)]()) {(xs, ys) => xs ::: ys} .filter(pair => isPrime(pair._1 + pair._2))List.range(1, n) .flatMap(i => List.range(1, i).map(x => (i, x))) .filter(pair => isPrime(pair._1 + pair._2))Where: class List[A] { defflatMap[B](f: A => List[B]): List[B] }for { i <- List.range(1, n) j <- List.range(1, i) if isPrime(i + j) } yield {i, j}List.range(1, n) .flatMap(i =>List.range(1, i) .filter(j => isPrime(i+j)) .map(j => (i, j)))
  • 24. Tony Hoare, who invented the null reference in 1965 while working on an object oriented language called ALGOL W, called its invention his “billion dollar mistake”Optionsvalcapitals = Map("Italy" -> "Rome", "Switzerland" -> "Bern", "Germany" -> "Berlin" , "France" -> "Paris")println(capitals.get("Italy")) // Some(Rome)println(capitals.get("Spain")) // Noneprintln(capitals.get("Italy").get) // Romeprintln(capitals.get("Spain").get) // thorwsExceptionprintln(capitals.get("Spain").getOrElse("Unknown")) // Unknown
  • 25. OptionsasMonadsdefmap[B](f: A => B): M[B]defflatMap[B](f: A => M[B]): M[B]deffilter(p: A => Boolean): M[A]defreadPositiveIntParam(params: Map[String, String], name: String): Int= paramsgetnameflatMapstringToIntfilter (_ > 0) getOrElse 0defstringToInt(string: String) : Option[Int] = try { Some(string.toInt)} catch { case _ : java.lang.NumberFormatException => None}defreadPositiveIntParam(params: Map[String, String], name: String): Int = (for{ param<- paramsgetname; value<- stringToInt(param) if (value > 0) } yieldvalue) getOrElse 0valparams = Map("a" -> "5", "b" -> "false", "c" -> "-3")valreadPositiveIntParam(params, "a") // == 5valreadPositiveIntParam(params, "b") // == 0 – Samefor "c" and "d"
  • 26. Signals and Monitorsdefsynchronized[A] (e: => A): Adefwait()defwait(msec: Long)defnotify()defnotifyAll()SyncVarclass SyncVar[A] { private var isDefined: Boolean = false private varvalue: A = _defget = synchronized { while (!isDefined) wait() value }defset(x: A) = synchronized { value = x; isDefined = true; notifyAll() }defisSet: Boolean = synchronized { isDefined }defunset = synchronized { isDefined= false }}
  • 27. Futuresdeffuture[A](p: => A): Unit => A = {valresult = new SyncVar[A] fork { result.set(p) } (() => result.get)}valx = future(someLengthyComputation)anotherLengthyComputationvaly = f(x()) + g(x())Semaphoresclass Lock {varavailable = truedefacquire = synchronized { while (!available) wait() available = false }defrelease = synchronized { available = true notify() }}Mailboxesclass MailBox {defsend(msg: Any)defreceive[A](f: PartialFunction[Any, A]): AdefreceiveWithin[A](msec: Long)(f: PartialFunction[Any, A]): A}
  • 28. ActorsclassPrinterActorextendsActor {defact() {while(true) { receive {casemsg=> println("Received message: " + msg) } } }}valprinterActor = newPrinterActorprinterActor.startprinterActor! "hi there“ // prints "Received message: hi there"printerActor ! 23 // prints "Received message: 23"
  • 29. Creating Actors with the actormethodimportscala.actors.Actor._valprinterActor = actor {while(true) { receive {case s: String => println("I got a String: " + s)case i: Int => println("I got an Int: " + i.toString)case _ => println(" I don’t know what I got ") } }}printerActor ! "hi there" // prints “I got a String: hi there”printerActor ! 23 // prints “I got an Int: 23”printerActor ! 3.33 // prints “I don’t know what I got”
  • 30. reactinstead of receive (whenpossible)importscala.actors.Actor._valprinterActor = actor { loop {react {case s: String => println("I got a String: " + s)case i: Int => {println("I got an Int: " + i.toString)println(“Waiting for another Int")react {case j: Int=> println(“Another Int: " + j.toString) } }case _ => exit } }}
  • 31. Message types! send an asynchronous message which means that the sending actor does not wait until the message is received; its execution continues immediately. All actors have a mailbox which buffers incoming messages until they are processed!? senda synchronous message: causes the sending actor to wait until a response is received which is then returned. There is an overloaded variant taking a timeout and returning an Option[Any] instead of Any!! similar to !? In the sensethatitallows to get an answer from the receiver. However, instead of blocking the sending actor until a response is received, it returns Future instance that can be used to retrieve the receiver’s response once it is available
  • 32. Remote Actorsactor { // SERVER ACTORRemoteActor.classLoader = getClass().getClassLoader() alive(9000) // starts remote actor listening on the given port register('Server, self) // registers the actor using the symbolloop {receive {case Message => sender ! ... } }} actor { // CLIENT ACTORtrapExit= true // listens exit of linked actorsRemoteActor.classLoader= getClass().getClassLoader()alive(9001)valserver = select(Node("127.0.0.1", 9000), 'Server) link(server) // linksthisactor to the server one server ! Message // sends a Message to the server}