• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Scala - where objects and functions meet
 

Scala - where objects and functions meet

on

  • 1,978 views

 

Statistics

Views

Total Views
1,978
Views on SlideShare
1,856
Embed Views
122

Actions

Likes
3
Downloads
33
Comments
1

4 Embeds 122

http://www.programmersinpadua.it 90
https://twitter.com 19
http://www.linkedin.com 11
https://www.linkedin.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

11 of 1 previous next

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • Mario, thank you so much for your excellent presentation of Scala held in Padua during last meet of 'programmers in padua' and thank you also for the slide condivision!
    Good luck for your new job in Germany... and for your family!
    -- Francesco, a partecipant of ProgrmmmersInPadua
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Scala - where objects and functions meet Scala - where objects and functions meet Presentation Transcript

    • Whereobjects and functionsmeet
      by Mario Fusco
      mario.fusco@gmail.com
      twitter: @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 Simple
      Vs.
      Do More With Less
    • statically typed
      object-oriented
      functional
      scriptable
      Why Scala?
      concise
      Java compatible
      extensible
      concurrent
    • The first Scala class
      class Rational(n: Int, d: Int) {
      valnum = n
      val den = d
      defthis(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 parameters
      classRational(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 = RationalOne
      valtwo = Rational(1) + one
      val two = Rational(1).+(one)
    • Traits
      classAnimal { defeat(): Unit }
      traitMammalextendsAnimal { defgiveBirth(): Mammal }
      traitHasWingsextendsAnimal { deffly(): Unit }
      traitHasLegsextendsAnimal { defwalk(): Unit }
      class Snake extendsAnimal
      classFrogextendsAnimal with HasLegs
      classCatextendsAnimalwithMammalwithHasLegs
      classBatextendsAnimalwithMammalwithHasWings
      class Chimera extendsAnimalwithMammalwithHasWingswithHasLegs
    • Let’s put alltogether
      trait IntSet {
      defcontains(x: Int): Boolean
      defnotContains(x: A) = !contains(x)
      defadd(x: Int): IntSet
      }
      object EmptySetextends IntSet {
      defcontains(x: Int): Boolean = false
      defadd(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 true
      defadd(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
      }
    • GenericTypes
      trait Set[A <: Ordered[A]] {
      def contains(x: A): Boolean
      def add(x: A): Set[A]
      }
      classEmptySet[A <: Ordered[A]] extends Set[A] {
      def contains(x: A): Boolean = false
      def 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 x
      else if (x > elem) right contains x
      elsetrue
      def 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 classes
      sealed traitExpr
      case class Var(name: String) extendsExpr
      case class Number(num: Double) extendsExpr
      case class Unop(op: String, arg: Expr) extendsExpr
      case class Binop(op: String, l: Expr, r: Expr) extendsExpr
    • Pattern matching
      def simplify(expr: Expr): Expr = exprmatch {
      caseUnop("-", Unop("-", e)) => e // Double negation
      caseBinop("+", e, Number(0)) => e // Adding zero
      caseBinop("*", e, Number(1)) => e // Multiplying by one
      case _ => expr
      }
      // Simplify double negation: simplified = Var("x")
      val simplified = simplify(Unop("-", Unop("-", Var("x"))))
    • Tuples
      valpair = (2, "items")
      println(pair._1) // prints 2
      println(pair._2) // printsitems
      defdivmod(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 Function
      defsum(f: Int => Int, a: Int, b: Int): Int=
      if (a > b) 0 else f(a) + sum(f, a + 1, b)
      defid(x: Int): Int = x
      defsumInts(a: Int, b: Int): Int = sum(id, a, b)
      defsquare(x: Int): Int = x * x
      defsumSquares(a: Int, b: Int): Int = sum(square, a, b)
      Anonymous Function
      defsumInts(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 Curry
      defsum(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
      }
    • Implicitparameters
      abstractclassAggregator[A] {
      defunit: A
      defadd(x: A, y: A): A
      }
      objectstringAggregatorextendsAggregator[String] {
      defunit= ""
      defadd(x: String, y: String): String = x concaty
      }
      objectintAggregatorextendsAggregator[Int] {
      defunit= 0
      defadd(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 =
    • Implicitconversion
      val a = new Rational(2, 3)
      val b = a + 2 // = 8/3
      val c = 2 + a // Compilation Error
      implicitdefintToRational(x: Int) = newRational(x)
      valc = 2 + a // = 8/3
      Viewbound
      traitSet[A <% Rational]
    • Duck typing is the dynamic mechanism that allows to discover a dog cannot say quack only at runtime
      ... in production
      ... on friday evening
      Structural 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)
      compilation
      error
      runtime error
    • Lists
      valletters: List[String] = List("a", "b", "c", "d")
      valemptyList = Nil
      valletters= "a" :: "b" :: "c" :: "d" :: Nil
      x :: ysisequivalent to ys.::(x) // infix operator == right associative
      xs ::: 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 Lists
      valanimals = 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-Comprehensions
      for (p <- personsifp.age > 20) yield p.name
      personsfilter (p => p.age > 20) map (p => p.name)
      for {
      p <- persons // Generators
      c <- p.children
      if c.name startsWith"A" // Filter
      } yield p.name // Map
    • Given n>0 findallpairs iand j where 1 ≤j ≤ i ≤ n and i+jis prime
      List.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”
      Options
      valcapitals = Map("Italy" -> "Rome", "Switzerland" -> "Bern",
      "Germany" -> "Berlin" , "France" -> "Paris")
      println(capitals.get("Italy")) // Some(Rome)
      println(capitals.get("Spain")) // None
      println(capitals.get("Italy").get) // Rome
      println(capitals.get("Spain").get) // thorwsException
      println(capitals.get("Spain").getOrElse("Unknown")) // Unknown
    • OptionsasMonads
      defmap[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 0
      defstringToInt(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 0
      valparams = Map("a" -> "5", "b" -> "false", "c" -> "-3")
      valreadPositiveIntParam(params, "a") // == 5
      valreadPositiveIntParam(params, "b") // == 0 – Samefor "c" and "d"
    • Signals and Monitors
      defsynchronized[A] (e: => A): A
      defwait()
      defwait(msec: Long)
      defnotify()
      defnotifyAll()
      SyncVar
      class 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 }
      }
    • Futures
      deffuture[A](p: => A): Unit => A = {
      valresult = new SyncVar[A]
      fork { result.set(p) }
      (() => result.get)
      }
      valx = future(someLengthyComputation)
      anotherLengthyComputation
      valy = f(x()) + g(x())
      Semaphores
      class Lock {
      varavailable = true
      defacquire = synchronized {
      while (!available) wait()
      available = false
      }
      defrelease = synchronized {
      available = true
      notify()
      }
      }
      Mailboxes
      class MailBox {
      defsend(msg: Any)
      defreceive[A](f: PartialFunction[Any, A]): A
      defreceiveWithin[A](msec: Long)(f: PartialFunction[Any, A]): A
      }
    • Actors
      classPrinterActorextendsActor {
      defact() {
      while(true) {
      receive {
      casemsg=> println("Received message: " + msg)
      }
      }
      }
      }
      valprinterActor = newPrinterActor
      printerActor.start
      printerActor! "hi there“ // prints "Received message: hi there"
      printerActor ! 23 // prints "Received message: 23"
    • Creating Actors with the actormethod
      importscala.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 Actors
      actor { // SERVER ACTOR
      RemoteActor.classLoader = getClass().getClassLoader()
      alive(9000) // starts remote actor listening on the given port
      register('Server, self) // registers the actor using the symbol
      loop {
      receive {case Message => sender ! ... }
      }
      }
      actor { // CLIENT ACTOR
      trapExit= true // listens exit of linked actors
      RemoteActor.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
      }