SlideShare a Scribd company logo
SCALA ДЛЯ ДЖЕДАЕВ
      Владимир Парфиненко
   vladimir.parfinenko@gmail.com
               @cypok
THE LIGHT SIDE
THE DARK SIDE
TYPES
OPTION
val set = Set(42, null, "Yoda")
val found = set find { _ == null }

if (found != null) {
  // huh, we've found it or not?
  println(s"Found $found!")
} else {
  println("Not found.")
}
OPTION
val set = Set(42, null, "Yoda")
val found = set find { _ == null }

found match {
  case Some(elem) => println(s"Found $elem!")
  case None => println("Not found.")
}




                                  olation
                                                2 .10

                    string interp
TYPES ON STEROIDS
sealed abstract class Option[+A] {
  def get: A
}

final case class Some[+A](x: A) extends Option[A] {
  def get = x
}

case object None extends Option[Nothing] {
  def get = throw new NoSuchElementException("None.get")
}
TYPE COVARIANCE
                           not im        2 .10
                                 pleme
class Cell[T](x: T) {                  nte d
  def get: T = ???
  def set(x: T) { ??? }
}

val c1 = new Cell[String]("Anakin")

val c2: Cell[Any] = c1 // type mismatch
TYPE COVARIANCE

class Cell[+T](x: T) {
  def get: T = ???
}

val c1 = new Cell[String]("Anakin")

val c2: Cell[Any] = c1
val jedi = c2.get
TYPE COVARIANCE

class Cell[+T](x: T) {
  def get: T = ???
  def set(x: T) { ??? } // compilation error
}

val c1 = new Cell[String]("Anakin")

val c2: Cell[Any] = c1
c2.set(37)
TYPE COVARIANCE

class Cell[-T](x: T) {
  def get: T = ??? // compilation error
  def set(x: T) { ??? }
}

val c1 = new Cell[Any](37)

val c2: Cell[String] = c1
val jedi = c2.get
TYPE COVARIANCE

class Cell[-T](x: T) {
  def set(x: T) { ??? }
}

val c1 = new Cell[Any]('Anakin)

val c2: Cell[String] = c1
c2.set("Darth Vader")
LOWER & UPPER BOUNDS
 class List[+A] {
   def ++[B >: A](that: List[B]): List[B] = ???
 }

 val strs = List("Leia", "Organa")
 val syms = List('Anakin, 'Skywalker)
 val all = strs ++ syms // List[java.io.Serializable]




 def max[A <: Ordered[_]](xs: List[A]): A = ???
 val accounts: List[Money]
 max(accounts)
CONTEXT BOUNDS
trait Jedi { def force: Double }

val jediOrder: Set[Jedi]
val grandMaster = jediOrder.max
  // No implicit Ordering defined for Jedi.

implicit val jediOrdering = new Ordering[Jedi] {
  def compare(j1: Jedi, j2: Jedi) = j1.force.compare(j2.force)
}

val grandMaster = jediOrder.max



trait TraversableOnce[+A] {
  def max[B >: A](implicit cmp: Ordering[B]): A = ???
  def max[A : Ordering]: A = ???
}
TYPES HIERARCHY
                                    Any



            AnyVal                             AnyRef/Object



                                                           ScalaObject

Value classes        Primitives             Java classes
2.10                                                    Scala classes

                                                    Null


                                  Nothing
TYPES ON STEROIDS
sealed abstract class Option[+A] {
  def get: A
}

final case class Some[+A](x: A) extends Option[A] {
  def get = x
}

case object None extends Option[Nothing] {
  def get = throw new NoSuchElementException("None.get")
}
PARALLELISM & CONCURRENCY
PARALLEL COLLECTIONS
val nums = (1 to 10).par
nums foreach { x => print(x + " ") }
  // 1 2 8 9 10 7 5 6 3 4

nums reduce { _ - _ }
  // -15

nums reduce { _ - _ }
  // 5

nums reduce { _ + _ }
  // 55

val word = Seq("G", "r", "i", "e", "v", "o", "u", "s")
word.par reduce { _ ++ _ }
  // Grievous
2.10
                      FUTURES


• Хранилище   для значения, которое будет получено в
 будущем

• Получениезначения может быть выполнено асинхронно и
 не блокировать программу

• Значение   может быть не получено вовсе
FUTURES
val f: Future[List[String]] = future {
  session.getRecentPosts
}

f onSuccess {
  case posts =>
    for (post <- posts) println(post)
}

f onFailure {
  case t =>
    println("An error has occured: " + t.getMessage)
}
FOR

val files: Seq[File]

for (file <- files) {
  println(file.getName)
}
FOR

def fileLines(f: File): Seq[String] = ???

for (file <- files) {
  if (!file.getName.startsWith(".")) {
    for (line <- fileLines(file)) {
      if (line.nonEmpty) {
        println(file + ": " + line)
      }
    }
  }
}
FOR
for {
  file <- files
  if !file.getName.startsWith(".")
  line <- fileLines(file)
  if line.nonEmpty
} println(file + ": " + line)

files withFilter { !_.getName.startsWith(".") } foreach { file =>
  fileLines withFilter { _.nonEmpty } foreach { line =>
    println(file + ": " + line)
  }
}
FOR
val lines = for {
  file <- files
  if !file.getName.startsWith(".")
  line <- fileLines(file)
  if line.nonEmpty
} yield (file + ": " + line)

files withFilter { !_.getName.startsWith(".") } flatMap { file =>
  fileLines(file) withFilter { _.nonEmpty } map { line =>
    file + ": " + line
  }
}
FUTURES

val usdQuote = future { connection.getCurrentValue(USD) }
val chfQuote = future { connection.getCurrentValue(CHF) }

val purchase = for {
  usd <- usdQuote
  chf <- chfQuote
  if isProfitable(usd, chf)
} yield connection.buy(amount, chf)

purchase onSuccess {
  case _ => println(s"Purchased $amount CHF")
}
FUTURES
  val rateQuote = future {
    connection.getCurrentValue(USD)
  }

  val purchase = rateQuote map { quote =>
    if (isProfitable(quote)) connection.buy(amount, quote)
    else throw new Exception("not profitable")
  }

  purchase onSuccess {
    case _ => println(s"Purchased $amount USD")
  }



filter, fallbackTo, recoverWith, andThen, …
PROMISES
val p = promise[T]
val f = p.future

val producer = future {
  val r = produceSomething()
  p success r
  continueDoingSomethingUnrelated()
}

val consumer = future {
  startDoingSomething()
  f onSuccess {
    case r => doSomethingWithResult()
  }
}
PROMISES
def first[T](f: Future[T], g: Future[T]): Future[T] = {
  val p = promise[T]

    f onSuccess {
      case x => p.tryComplete(x)
    }

    g onSuccess {
      case x => p.tryComplete(x)
    }

    p.future
}
2.10
              ACTORS & AKKA


• Акторы   – это приватные данные и описание поведения

• Общение между акторами только через сообщения с
 неизменяемыми данными

• Акторы могут создавать других акторов и управлять ими в
 случае исключительных ситуаций
ACTORS
class MyActor extends Actor {
  def receive = {
    case "test" => log("received test")
    case _      => log("received unknown message")
  }
}

object Main extends App {
  val system = ActorSystem("MySystem")
  val myActor = system.actorOf(Props[MyActor], name = "myactor")
  myActor ! "test"
}
ACTORS
class Squarer extends Actor {
  def receive = {
    case x: Int => sender ! (x * x)
    case x: Double => sender ! (x * x)
  }
}

class Mathematician extends Actor {
  val squarer = context.actorOf(Props[Squarer], name = "squarer")
  def receive = {
    case x: Int =>
      (squarer ? x) onComplete {
        case Success(x) => log(x)
        case Failure => fail()
      }
  }
}
OTHER FEATURES
{
                                                                  on[ A] =
                                                             ti
                                                    n)) : Op
                                                    ea                              trait
                                           =>  Bool                                      Provi
                                 , p : (A                                            def s      der {
       rec              Lis t[A]                                                   }
                                                                                           mth:
                                                                                                 Int
@ tail         A]( xs:
       f ind[                                                  p)
 def        tch
                 {
                            ne                         (ta il,
    x s ma         l = > No      =>               find                             class
              e Ni        tail                lse                                          LazyO
         c as          ::            hea d) e                                       lazy       ne ex
                                                                                                     tends
                head        ) S ome(                                                       val s           Provi
         case          ead)                                                            ???       mth =           der {
                   p(h                                                                                 {
              if (                                                                 }
        }                                                                  }

    }
                      assert(assertion: Boolean, message: => Any): Unit

                      assert(true, { ??? })
                      assert(false, { ??? })

                                                                                                                ?
                                                                                  my                     t = ??
              2.10                                                           age                    : In        ?
                                                                        pack      o o {      v al x     t  = ??
     implicit
               class Ro                                                  cla ss F e[this]         y : In = ???
                        ckString                                                vat          val       nt
      def rock
                () = ???         (str: St
                                          ring) {                           pri      e[ Foo] al z: I
    }                                                                        pr ivat [my] v
                                                                                      e
    "foo".ro                                                                  pr ivat
             ck()
                                                                               }




                         val xml = <and><much>More!</much></and>

More Related Content

Scala for Jedi

  • 1. SCALA ДЛЯ ДЖЕДАЕВ Владимир Парфиненко vladimir.parfinenko@gmail.com @cypok
  • 5. OPTION val set = Set(42, null, "Yoda") val found = set find { _ == null } if (found != null) { // huh, we've found it or not? println(s"Found $found!") } else { println("Not found.") }
  • 6. OPTION val set = Set(42, null, "Yoda") val found = set find { _ == null } found match { case Some(elem) => println(s"Found $elem!") case None => println("Not found.") } olation 2 .10 string interp
  • 7. TYPES ON STEROIDS sealed abstract class Option[+A] { def get: A } final case class Some[+A](x: A) extends Option[A] { def get = x } case object None extends Option[Nothing] { def get = throw new NoSuchElementException("None.get") }
  • 8. TYPE COVARIANCE not im 2 .10 pleme class Cell[T](x: T) { nte d def get: T = ??? def set(x: T) { ??? } } val c1 = new Cell[String]("Anakin") val c2: Cell[Any] = c1 // type mismatch
  • 9. TYPE COVARIANCE class Cell[+T](x: T) { def get: T = ??? } val c1 = new Cell[String]("Anakin") val c2: Cell[Any] = c1 val jedi = c2.get
  • 10. TYPE COVARIANCE class Cell[+T](x: T) { def get: T = ??? def set(x: T) { ??? } // compilation error } val c1 = new Cell[String]("Anakin") val c2: Cell[Any] = c1 c2.set(37)
  • 11. TYPE COVARIANCE class Cell[-T](x: T) { def get: T = ??? // compilation error def set(x: T) { ??? } } val c1 = new Cell[Any](37) val c2: Cell[String] = c1 val jedi = c2.get
  • 12. TYPE COVARIANCE class Cell[-T](x: T) { def set(x: T) { ??? } } val c1 = new Cell[Any]('Anakin) val c2: Cell[String] = c1 c2.set("Darth Vader")
  • 13. LOWER & UPPER BOUNDS class List[+A] { def ++[B >: A](that: List[B]): List[B] = ??? } val strs = List("Leia", "Organa") val syms = List('Anakin, 'Skywalker) val all = strs ++ syms // List[java.io.Serializable] def max[A <: Ordered[_]](xs: List[A]): A = ??? val accounts: List[Money] max(accounts)
  • 14. CONTEXT BOUNDS trait Jedi { def force: Double } val jediOrder: Set[Jedi] val grandMaster = jediOrder.max // No implicit Ordering defined for Jedi. implicit val jediOrdering = new Ordering[Jedi] { def compare(j1: Jedi, j2: Jedi) = j1.force.compare(j2.force) } val grandMaster = jediOrder.max trait TraversableOnce[+A] { def max[B >: A](implicit cmp: Ordering[B]): A = ??? def max[A : Ordering]: A = ??? }
  • 15. TYPES HIERARCHY Any AnyVal AnyRef/Object ScalaObject Value classes Primitives Java classes 2.10 Scala classes Null Nothing
  • 16. TYPES ON STEROIDS sealed abstract class Option[+A] { def get: A } final case class Some[+A](x: A) extends Option[A] { def get = x } case object None extends Option[Nothing] { def get = throw new NoSuchElementException("None.get") }
  • 18. PARALLEL COLLECTIONS val nums = (1 to 10).par nums foreach { x => print(x + " ") } // 1 2 8 9 10 7 5 6 3 4 nums reduce { _ - _ } // -15 nums reduce { _ - _ } // 5 nums reduce { _ + _ } // 55 val word = Seq("G", "r", "i", "e", "v", "o", "u", "s") word.par reduce { _ ++ _ } // Grievous
  • 19. 2.10 FUTURES • Хранилище для значения, которое будет получено в будущем • Получениезначения может быть выполнено асинхронно и не блокировать программу • Значение может быть не получено вовсе
  • 20. FUTURES val f: Future[List[String]] = future { session.getRecentPosts } f onSuccess { case posts => for (post <- posts) println(post) } f onFailure { case t => println("An error has occured: " + t.getMessage) }
  • 21. FOR val files: Seq[File] for (file <- files) { println(file.getName) }
  • 22. FOR def fileLines(f: File): Seq[String] = ??? for (file <- files) { if (!file.getName.startsWith(".")) { for (line <- fileLines(file)) { if (line.nonEmpty) { println(file + ": " + line) } } } }
  • 23. FOR for { file <- files if !file.getName.startsWith(".") line <- fileLines(file) if line.nonEmpty } println(file + ": " + line) files withFilter { !_.getName.startsWith(".") } foreach { file => fileLines withFilter { _.nonEmpty } foreach { line => println(file + ": " + line) } }
  • 24. FOR val lines = for { file <- files if !file.getName.startsWith(".") line <- fileLines(file) if line.nonEmpty } yield (file + ": " + line) files withFilter { !_.getName.startsWith(".") } flatMap { file => fileLines(file) withFilter { _.nonEmpty } map { line => file + ": " + line } }
  • 25. FUTURES val usdQuote = future { connection.getCurrentValue(USD) } val chfQuote = future { connection.getCurrentValue(CHF) } val purchase = for { usd <- usdQuote chf <- chfQuote if isProfitable(usd, chf) } yield connection.buy(amount, chf) purchase onSuccess { case _ => println(s"Purchased $amount CHF") }
  • 26. FUTURES val rateQuote = future { connection.getCurrentValue(USD) } val purchase = rateQuote map { quote => if (isProfitable(quote)) connection.buy(amount, quote) else throw new Exception("not profitable") } purchase onSuccess { case _ => println(s"Purchased $amount USD") } filter, fallbackTo, recoverWith, andThen, …
  • 27. PROMISES val p = promise[T] val f = p.future val producer = future { val r = produceSomething() p success r continueDoingSomethingUnrelated() } val consumer = future { startDoingSomething() f onSuccess { case r => doSomethingWithResult() } }
  • 28. PROMISES def first[T](f: Future[T], g: Future[T]): Future[T] = { val p = promise[T] f onSuccess { case x => p.tryComplete(x) } g onSuccess { case x => p.tryComplete(x) } p.future }
  • 29. 2.10 ACTORS & AKKA • Акторы – это приватные данные и описание поведения • Общение между акторами только через сообщения с неизменяемыми данными • Акторы могут создавать других акторов и управлять ими в случае исключительных ситуаций
  • 30. ACTORS class MyActor extends Actor { def receive = { case "test" => log("received test") case _ => log("received unknown message") } } object Main extends App { val system = ActorSystem("MySystem") val myActor = system.actorOf(Props[MyActor], name = "myactor") myActor ! "test" }
  • 31. ACTORS class Squarer extends Actor { def receive = { case x: Int => sender ! (x * x) case x: Double => sender ! (x * x) } } class Mathematician extends Actor { val squarer = context.actorOf(Props[Squarer], name = "squarer") def receive = { case x: Int => (squarer ? x) onComplete { case Success(x) => log(x) case Failure => fail() } } }
  • 33. { on[ A] = ti n)) : Op ea trait => Bool Provi , p : (A def s der { rec Lis t[A] } mth: Int @ tail A]( xs: f ind[ p) def tch { ne (ta il, x s ma l = > No => find class e Ni tail lse LazyO c as :: hea d) e lazy ne ex tends head ) S ome( val s Provi case ead) ??? mth = der { p(h { if ( } } } } assert(assertion: Boolean, message: => Any): Unit assert(true, { ??? }) assert(false, { ??? }) ? my t = ?? 2.10 age : In ? pack o o { v al x t = ?? implicit class Ro cla ss F e[this] y : In = ??? ckString vat val nt def rock () = ??? (str: St ring) { pri e[ Foo] al z: I } pr ivat [my] v e "foo".ro pr ivat ck() } val xml = <and><much>More!</much></and>