Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scala for Jedi

Scala for Jedi

Второе выступление в рамках спецкурса "Немейнстримовые технологии разработки", читаемого в НГУ. http://bit.ly/mainstreamless

Avatar for Vladimir Parfinenko

Vladimir Parfinenko

December 07, 2012
Tweet

More Decks by Vladimir Parfinenko

Other Decks in Programming

Transcript

  1. 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.") }
  2. 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.") } string interpolation 2.10
  3. 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") }
  4. TYPE COVARIANCE not implemented 2.10 class Cell[T](x: T) { def

    get: T = ??? def set(x: T) { ??? } } val c1 = new Cell[String]("Anakin") val c2: Cell[Any] = c1 // type mismatch
  5. 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
  6. 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)
  7. 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
  8. 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")
  9. 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)
  10. 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 = ??? }
  11. 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") }
  12. 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
  13. FUTURES 2.10 • Хранилище для значения, которое будет получено в

    будущем • Получение значения может быть выполнено асинхронно и не блокировать программу • Значение может быть не получено вовсе
  14. 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) }
  15. FOR def fileLines(f: File): Seq[String] = ??? for (file <-

    files) { if (!file.getName.startsWith(".")) { for (line <- fileLines(file)) { if (line.nonEmpty) { println(file + ": " + line) } } } }
  16. 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) } }
  17. 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 } }
  18. 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") }
  19. 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, …
  20. 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() } }
  21. 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 }
  22. ACTORS & AKKA 2.10 • Акторы – это приватные данные

    и описание поведения • Общение между акторами только через сообщения с неизменяемыми данными • Акторы могут создавать других акторов и управлять ими в случае исключительных ситуаций
  23. 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" }
  24. 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() } } }
  25. @tailrec def find[A](xs: List[A], p: (A => Boolean)): Option[A] =

    { xs match { case Nil => None case head :: tail => if (p(head)) Some(head) else find(tail, p) } } trait Provider { def smth: Int } class LazyOne extends Provider { lazy val smth = { ??? } } assert(assertion: Boolean, message: => Any): Unit assert(true, { ??? }) assert(false, { ??? }) implicit class RockString(str: String) { def rock() = ??? } "foo".rock() 2.10 package my class Foo { private[this] val x: Int = ??? private[Foo] val y: Int = ??? private[my] val z: Int = ??? } val xml = <and><much>More!</much></and>