Scala
для

Java программистов

Павел Павлов
О себе
Занимаюсь системным программированием
● компиляторы, среды исполнения
● Excelsior JET - JVM with AOT compiler
● код...
Одна история из
реальной жизни
Excelsior JET
● Полная реализация Java SE
○ первый релиз - 2000 год
○ с 2005 сертифицирована как Java Compatible

● AOT Co...
Excelsior JET
● Одна из 4х Java SE VM, сделанных с нуля
○
○
○
○

Sun/Oracle HotSpot
JRockit
IBM J9
Excelsior JET

● Было: ...
Требования к языку
● Возможность создавать большие системы
○ и долгоживущие
○ и сложные

● Производительность

● статическ...
Требования к языку
● Возможность создавать большие системы
○ и долгоживущие
○ и сложные

● Производительность

● Java и/ил...
Требования к языку
● Возможность создавать большие системы
○ и долгоживущие
○ и сложные

● Производительность
● Самопримен...
Требования к языку
● Возможность создавать большие системы
○ и долгоживущие
○ и сложные

● Производительность
● Самопримен...
И тут я наткнулся на Scala
JET на Scala: наш опыт
●
●
●
●

Оптимизирующий компилятор
Новое ядро, implemented from scratch
R&D "по-взрослому"
Команда:...
Что такое Scala?
Язык Scala: характеристика
● компилируемый
● строго статически типизированный
● автоматический вывод типов (type
inference...
Язык Scala: цели
● Язык общего назначения
● Альтернатива/замена Java
● Внедрение FP в mainstream
● Преодоление "застоя" в ...
Java
C#

Ruby
Erlang
JavaScript
Python

C

Clojure
Haskell
PHP

C++
Go

Lua
Groovy
Язык Scala: история
Язык Scala: история

Martin Odersky
Язык Scala: история

Martin Odersky

Philip Wadler
Язык Scala: история
Автор: Martin Odersky (EPFL)
1995-2001 Pizza language (Odersky & Wadler)
"better Java": Java + generic...
Success story: Twitter
● 2006: начало - всё на Ruby on Rails
● 2007-2008: взрывной рост популярности
Success story: Twitter
● 2006: начало - всё на Ruby on Rails
● 2007-2008: взрывной рост популярности
Решение:

+
Популярность Scala
● 11 место - RedMonk Programming Language
Rankings (StackOverflow, GitHub)
● 36 место - TIOBE index
(по...
http://www.infoq.com/research/next-jvm-language
Инструменты
Hello, REPL!
scala> val repl = Map('R' -> "Read", 'E' -> "Eval",
|

'P' -> "Print", 'L' -> "Loop")

repl: immutable.Map[Ch...
Синтаксис: values & variables
val x: Int = 42
val ys = List(1, 2, 3)

// y: List[Int]

var z = "hello"

// z: String
Синтаксис: values & variables
val x: Int = 42
val ys = List(1, 2, 3)

// y: List[Int]

var z = "hello"

// z: String

make...
Синтаксис: functions
val x: Int = 42
val ys = List(1, 2, 3)

// y: List[Int]

var z = "hello"

// z: String

def max(a: In...
Синтаксис: основы
val x: Int = 42
val ys = List(1, 2, 3)

// y: List[Int]

var z = "hello"

// z: String

def max(a: Int, ...
Классы и объекты
abstract class Animal {
def name: String
}
class Person(firstName: String, lastName: String)
extends Anim...
Traits: множественное наследование
с человеческим лицом
trait Ordered[A] {
def compare(that: A): Int
def <

(that: A): Boo...
Types hierarchy
Operators are methods
List(1, 2, 3).map(inc)

// List(2, 3, 4)

List(1, 2, 3) map inc

// <- операторный синтаксис

abstra...
Functions are objects
Функциональные типы: (A => B)
trait Function1[A, B] {
def apply(x: A): B
}
val inc = { x: Int => x +...
Вызов и индексация
val inverse = { x: Int => 1.0 / x }
inverse(1)

// =>

inverse.apply(1)

val a = Array(0.33, 0.5) // =>...
Pattern matching
val anything: Any = ...
val str = anything match {
case 1

=> "one"

case x: Int if x > 0

=>

"positive ...
Алгебраические типы
type List[T] = Nil
| Cons(head: T, tail: List[T])
type Option[T] = None
| Some(value: T)
type Tree[T] ...
ADT in action
sealed class Expr
case class Var(name: String) extends Expr
case class Num(value: Int) extends Expr
case cla...
Pattern matching: extractors
object PowerOfTwo {
import java.lang.Long.{numberOfLeadingZeros => nlz}
def apply(i: Int): Lo...
Коллекции & итерация
Коллекции - первая по важности вещь после
собственно языковых фич
● Они вездесущи
● Дизайн стандартно...
Scala Collections
Scala Collections: API
● functional-style
● collect, count, exists, filter, find, flatMap, fold, forall,
●

foreach, group...
for comprehension
● обобщённый цикл for
○ с поддержкой фильтров и pattern matching

●
●
●
●

преобразователь потоков данны...
for loop: basic form
val files: Seq[File] = ...
for (file <- files) {
println(file.getName)
}
files foreach { file =>
prin...
for loop: filters & nested loops
def content(f: File): Seq[String] = ???
for {
file <- files
if !file.getName.startsWith("...
for loop: filters & nested loops
def content(f: File): Seq[String] = ???
val lines = for {
file <- files
if !file.getName....
Implicits
●
●
●
●

Extension methods
Automatic adaptors
DSLs
Typeclass pattern (C++ concepts)
Internal DSLs
Строковые интерполяторы
val name = "John"
s"Hello, $name" // то же, что "Hello, " + name
println(f"$companyName%15s")
val ...
Строковые интерполяторы
Простейший html-интерполятор для Play:
val link = "http://example.com"
val userName = "Joe"
val co...
Строковые интерполяторы
Простейший html-интерполятор для Play:
implicit class HtmlInterpolatorHelper(val sc: StringContext...
Parallelism & concurrency
val people: Seq[Person] = ...
val (minors, adults) = people partition (_.age < 18)
Parallelism & concurrency
val people: Seq[Person] = ...
val (minors, adults) = people.par partition (_.age < 18)
Parallelism & concurrency
val people: Seq[Person] = ...
val (minors, adults) = people.par partition (_.age < 18)
actor {
r...
Асинхронность: Futures
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onSuccess {
case posts =>
for (p ...
Combining futures with ‘for’
val usdQuote = future { connection.getCurrentValue(USD) }
val chfQuote = future { connection....
Akka
● Toolkit & runtime for building concurrent,
distributed & fault tolerant applications
● Actors
● Remoting: location ...
Tools
IDEs: IDEA, Eclipse, NetBeans
+ Emacs, vim, Sublime, TextMate
Building: SBT
but also ant, Maven, etc...
Testing: Sca...
Libraries & frameworks
DB query & access: Slick (LINQ-like)
UI: ScalaFX
Text processing: parser combinators (stdlib)
GPGPU...
Как правильно начать?
●
●
●
●
●

Хотя бы один эксперт - большой плюс
Не увлекайтесь фичами
Периодический рефакторинг
Испол...
Novosibirsk Scala Enthusiasts
Q/A
Case classes and pattern matching
● Pattern matching - обобщённый switch/case
● Case classes - реализация ADT
Преимущества...
Case classes
case class Person(name: String, age: Int)

class Person(val name: String, val age: Int)
extends Serializable ...
Partial functions
trait Function1[T, R] {
def apply(x: T): R
}
trait PartialFunction[T, R] extends Function1[T, R] {
def i...
Promises
val p = promise[T}
val f = p.future
val producer = future {
val r = produceSomething()
p success r
continueDoingS...
Promises
def first[T}(f: Future[T], g: Future[T]): Future[T] = {
val p = promise[T]
f onSuccess { case x => p.tryComplete(...
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Upcoming SlideShare
Loading in …5
×

Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)

700 views
599 views

Published on

Published in: Technology, News & Politics
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
700
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)

  1. 1. Scala для Java программистов Павел Павлов
  2. 2. О себе Занимаюсь системным программированием ● компиляторы, среды исполнения ● Excelsior JET - JVM with AOT compiler ● код на орбите (ГЛОНАСС) Преподаю ● научное руководство студентами (НГУ) ● подготовка юниоров в компании Участник Scala community ● Scala core committer (stdlib, compiler) ● Организовал ScalaNsk
  3. 3. Одна история из реальной жизни
  4. 4. Excelsior JET ● Полная реализация Java SE ○ первый релиз - 2000 год ○ с 2005 сертифицирована как Java Compatible ● AOT Compiler + Java Runtime ○ смешанная компиляция: AOT + JIT ○ поддержка нестандартных загрузчиков классов в AOT режиме (для Eclipse RCP, Tomcat) ● Toolkit ○ Deployment ○ Startup Optimizer
  5. 5. Excelsior JET ● Одна из 4х Java SE VM, сделанных с нуля ○ ○ ○ ○ Sun/Oracle HotSpot JRockit IBM J9 Excelsior JET ● Было: очень древний codebase ○ заложен в конце 80х/начале 90х ○ код морально устарел ○ изменилось всё: требования, технологии, инструменты, процессы ○ куда податься?
  6. 6. Требования к языку ● Возможность создавать большие системы ○ и долгоживущие ○ и сложные ● Производительность ● статическая типизация ● развитые инструменты разработки ● промышленное качество
  7. 7. Требования к языку ● Возможность создавать большие системы ○ и долгоживущие ○ и сложные ● Производительность ● Java и/или C++
  8. 8. Требования к языку ● Возможность создавать большие системы ○ и долгоживущие ○ и сложные ● Производительность ● Самоприменимость ● Java
  9. 9. Требования к языку ● Возможность создавать большие системы ○ и долгоживущие ○ и сложные ● Производительность ● Самоприменимость ● Java? А как насчёт: ○ ○ ○ ○ скорости разработки? объёма кода? гибкости, мощи средств языка? в конце концов, количества fun’а?
  10. 10. И тут я наткнулся на Scala
  11. 11. JET на Scala: наш опыт ● ● ● ● Оптимизирующий компилятор Новое ядро, implemented from scratch R&D "по-взрослому" Команда: ≤5 человек ○ 4 из них не знали Скалу ● Время: 1.5 года * 4 человек ○ всё работает, релиз был в апреле 2013 ○ ~40kloc
  12. 12. Что такое Scala?
  13. 13. Язык Scala: характеристика ● компилируемый ● строго статически типизированный ● автоматический вывод типов (type inference) ● OOP + FP ● "лёгкий" синтаксис ● работает на платформе JVM ● бесшовная интеграция с Java
  14. 14. Язык Scala: цели ● Язык общего назначения ● Альтернатива/замена Java ● Внедрение FP в mainstream ● Преодоление "застоя" в OOP Целевая аудитория: 1. Java-программисты (народные массы) Лучший язык, FP 2. Ruby/Python(/JS)-программисты Статическая типизация, производительность 3. Функциональщики Использование FP в mainstream
  15. 15. Java C# Ruby Erlang JavaScript Python C Clojure Haskell PHP C++ Go Lua Groovy
  16. 16. Язык Scala: история
  17. 17. Язык Scala: история Martin Odersky
  18. 18. Язык Scala: история Martin Odersky Philip Wadler
  19. 19. Язык Scala: история Автор: Martin Odersky (EPFL) 1995-2001 Pizza language (Odersky & Wadler) "better Java": Java + generics, function types & closures, ADT & pattern matching 1997-1998 Generic Java generics & javac compiler => Java language 2001-2005 Scala 1.x "better than Java" 2006Scala 2.x 2009-2010 Проникновение в индустрию
  20. 20. Success story: Twitter ● 2006: начало - всё на Ruby on Rails ● 2007-2008: взрывной рост популярности
  21. 21. Success story: Twitter ● 2006: начало - всё на Ruby on Rails ● 2007-2008: взрывной рост популярности Решение: +
  22. 22. Популярность Scala ● 11 место - RedMonk Programming Language Rankings (StackOverflow, GitHub) ● 36 место - TIOBE index (поисковые запросы)
  23. 23. http://www.infoq.com/research/next-jvm-language
  24. 24. Инструменты
  25. 25. Hello, REPL! scala> val repl = Map('R' -> "Read", 'E' -> "Eval", | 'P' -> "Print", 'L' -> "Loop") repl: immutable.Map[Char,String] = Map(...) scala> for ((k, v) <- repl) println(s"$k is for $v") R is for Read E is for Eval P is for Print L is for Loop
  26. 26. Синтаксис: values & variables val x: Int = 42 val ys = List(1, 2, 3) // y: List[Int] var z = "hello" // z: String
  27. 27. Синтаксис: values & variables val x: Int = 42 val ys = List(1, 2, 3) // y: List[Int] var z = "hello" // z: String make val not var
  28. 28. Синтаксис: functions val x: Int = 42 val ys = List(1, 2, 3) // y: List[Int] var z = "hello" // z: String def max(a: Int, b: Int): Int = if (a > b) a else b def inc(x: Int) = x + 1 val inc = { x: Int => x + 1 } // inc: Int => Int
  29. 29. Синтаксис: основы val x: Int = 42 val ys = List(1, 2, 3) // y: List[Int] var z = "hello" // z: String def max(a: Int, b: Int): Int = if (a > b) a else b def inc(x: Int) = x + 1 val inc = { x: Int => x + 1 } // inc: Int => Int ys map inc // List(2, 3, 4) ys map { x => x + 1 } ys map { _ + 1 } ys filter { _ % 2 != 0 } // List(1, 3) ys reduce max // max(1, max(2, 3)) ys reduce { (x, y) => x + y } // 1 + 2 + 3
  30. 30. Классы и объекты abstract class Animal { def name: String } class Person(firstName: String, lastName: String) extends Animal { val name = firstName + " " + lastName } class Employee(firstName: String, lastName: String, val age: Int, var salary: Double) extends Person(firstName, lastName) object Main extends App { val p = new Employee("John", "Doe", 20, 300.0) println(p.name + " is + p.age + " years old") }
  31. 31. Traits: множественное наследование с человеческим лицом trait Ordered[A] { def compare(that: A): Int def < (that: A): Boolean = (this compare that) < 0 def > (that: A): Boolean = (this compare that) > 0 def <= (that: A): Boolean = (this compare that) <= 0 def >= (that: A): Boolean = (this compare that) >= 0 } class Money extends SomeTrait with Ordered[Money] { def compare(that: Money) = ... }
  32. 32. Types hierarchy
  33. 33. Operators are methods List(1, 2, 3).map(inc) // List(2, 3, 4) List(1, 2, 3) map inc // <- операторный синтаксис abstract class Set[T] { def contains(x: T): Boolean def - (x: T): Set[T] def !@#%^&*-+ : Int // <- пожалуй, так делать не стоит } def foo(s: Set[Int]) { if (s contains 42) println(s - 42) } 1 + 3*5 => 1.+(3.*(5))
  34. 34. Functions are objects Функциональные типы: (A => B) trait Function1[A, B] { def apply(x: A): B } val inc = { x: Int => x + 1 } val inc = new Function1[Int, Int] { def apply(x: Int): Int = { x + 1 } } inc(4) // inc.apply(4) // Function1[A, B]
  35. 35. Вызов и индексация val inverse = { x: Int => 1.0 / x } inverse(1) // => inverse.apply(1) val a = Array(0.33, 0.5) // => Array.apply(0.33, 0.5) a(1) /*0.5*/ // => a.apply(1) a(0) = 1.0 // => a.update(0, 1.0) def foo(f: Int => Double) { println(f(1)) // => println(f.apply(1)) } foo(inverse) // 1.0 foo(a) // 0.5 Array[T] is a function (Int => T)!
  36. 36. Pattern matching val anything: Any = ... val str = anything match { case 1 => "one" case x: Int if x > 0 => "positive integer" case x: Float if x > 0 => "positive float" case _: String => "string" case _ => "unknown" } “switch/case на стероидах”
  37. 37. Алгебраические типы type List[T] = Nil | Cons(head: T, tail: List[T]) type Option[T] = None | Some(value: T) type Tree[T] = Leaf | Branch(l, r: Tree[T], value: T)
  38. 38. ADT in action sealed class Expr case class Var(name: String) extends Expr case class Num(value: Int) extends Expr case class Neg(arg: Expr) extends Expr case class Add(arg1: Expr, arg2: Expr) extends Expr def optimize(expr: Expr): Expr = expr match { case Neg(Neg(x)) => optimize(x) case Add(x, Num(0)) => optimize(x) case Neg(Num(x)) => Num(-x) case Add(x, Neg(y)) if x == y => Num(0) case Add(Num(x), Num(y)) case Neg(x) => Neg(optimize(x)) case Add(x, y) => Add(optimize(x), optimize(y)) case _ } => Num(x + y) => expr
  39. 39. Pattern matching: extractors object PowerOfTwo { import java.lang.Long.{numberOfLeadingZeros => nlz} def apply(i: Int): Long = 1L << i def unapply(x: Long): Option[Int] = if (((x & (x-1)) == 0) && (x > 0)) Some(63 - nlz(x)) else None } def optimize(e: Expr) = e match { case Mul(x, PowerOfTwo(n)) => Shl(x, n) case Div(x, PowerOfTwo(n)) => Shr(x, n) case Rem(x, PowerOfTwo(n)) => And(x, PowerOfTwo(n) - 1) }
  40. 40. Коллекции & итерация Коллекции - первая по важности вещь после собственно языковых фич ● Они вездесущи ● Дизайн стандартной библиотеки коллекций влияет на каждую программу, причём в значительной степени ● Они формируют словарь, с помощью которого программист выражает свои мысли
  41. 41. Scala Collections
  42. 42. Scala Collections: API ● functional-style ● collect, count, exists, filter, find, flatMap, fold, forall, ● foreach, groupBy, map, max/min, partition, reduce, splitAt, take, to, ... примеры: val people: Seq[Person] = ... val (minors, adults) = people partition (_.age < 18) ● параллельные коллекции: .par, tuning (thread pools etc.)
  43. 43. for comprehension ● обобщённый цикл for ○ с поддержкой фильтров и pattern matching ● ● ● ● преобразователь потоков данных язык запросов монадический комбинатор всего лишь синтаксический сахар
  44. 44. for loop: basic form val files: Seq[File] = ... for (file <- files) { println(file.getName) } files foreach { file => println(file.getName) } val names = for (file <- files) yield file.getName val names = files map { _.getName }
  45. 45. for loop: filters & nested loops def content(f: File): Seq[String] = ??? for { file <- files if !file.getName.startsWith(".") line <- content(file) if line.nonEmpty } println(file + ": " + line) files withFilter (!_.getName.startsWith(".")) foreach { file => content(file) withFilter (_.nonEmpty) foreach { line => println(file + ": " + line) } }
  46. 46. for loop: filters & nested loops def content(f: File): Seq[String] = ??? val lines = for { file <- files if !file.getName.startsWith(".") line <- content(file) if line.nonEmpty } yield file + ": " + line files withFilter (!_.getName.startsWith(".")) flatMap { file => content(file) withFilter (_.nonEmpty) map { line => file + ": " + line } }
  47. 47. Implicits ● ● ● ● Extension methods Automatic adaptors DSLs Typeclass pattern (C++ concepts)
  48. 48. Internal DSLs
  49. 49. Строковые интерполяторы val name = "John" s"Hello, $name" // то же, что "Hello, " + name println(f"$companyName%15s") val a: Int = b"100011" sql"select * from user where id = $id"
  50. 50. Строковые интерполяторы Простейший html-интерполятор для Play: val link = "http://example.com" val userName = "Joe" val content = html""" <img src="user.png"/> $userName""" val result = html""" <a href="$link">$content</a>"""
  51. 51. Строковые интерполяторы Простейший html-интерполятор для Play: implicit class HtmlInterpolatorHelper(val sc: StringContext) extends AnyVal { def html(args: Any*): Html = { val strings = sc.parts.iterator val expressions = args.iterator val buffer = new StringBuilder(strings.next()) while(strings.hasNext) { val nextExpr = expressions.next() nextExpr match { case html: Html => buffer.append(html.toString) case other => buffer.append(HtmlFormat.escape(other.toString)) } buffer.append(strings.next()) } new Html(buffer) } }
  52. 52. Parallelism & concurrency val people: Seq[Person] = ... val (minors, adults) = people partition (_.age < 18)
  53. 53. Parallelism & concurrency val people: Seq[Person] = ... val (minors, adults) = people.par partition (_.age < 18)
  54. 54. Parallelism & concurrency val people: Seq[Person] = ... val (minors, adults) = people.par partition (_.age < 18) actor { receive { case people: Seq[Person] => val (minors, adults) = people partition (_.age < 18) School ! minors Work ! adults } }
  55. 55. Асинхронность: Futures val f: Future[List[String]] = future { session.getRecentPosts } f onSuccess { case posts => for (p <- posts) println(p) } f onFailure { case t => println("An error has occurred: " + t.getMessage) }
  56. 56. Combining futures with ‘for’ 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") }
  57. 57. Akka ● Toolkit & runtime for building concurrent, distributed & fault tolerant applications ● Actors ● Remoting: location transparent ● Supervision & monitoring ● Software Transactional Memory ● Dataflow concurrency
  58. 58. Tools IDEs: IDEA, Eclipse, NetBeans + Emacs, vim, Sublime, TextMate Building: SBT but also ant, Maven, etc... Testing: ScalaTest, Specs, ScalaCheck but also JUnit, EasyMock, Mockito, etc... Web frameworks: Lift, Play! but also Struts, Spring MVC, etc... + all that Java stuff
  59. 59. Libraries & frameworks DB query & access: Slick (LINQ-like) UI: ScalaFX Text processing: parser combinators (stdlib) GPGPU: ScalaCL ...and many others
  60. 60. Как правильно начать? ● ● ● ● ● Хотя бы один эксперт - большой плюс Не увлекайтесь фичами Периодический рефакторинг Используйте в юнит-тестах Изучив Scala Вы станете лучше писать на Java
  61. 61. Novosibirsk Scala Enthusiasts
  62. 62. Q/A
  63. 63. Case classes and pattern matching ● Pattern matching - обобщённый switch/case ● Case classes - реализация ADT Преимущества Scala: ● Case class - больше чем ADT: интерфейсы, методы, данные ● Pattern matching customizable by user: абстракция логики от структуры данных, DSLs
  64. 64. Case classes case class Person(name: String, age: Int) class Person(val name: String, val age: Int) extends Serializable { override def equals(other: AnyRef) = ... override def hashCode = ... override def toString = ... def copy(name: String = this.name, age: Int = this.age) = ... } object Person extends (String, Int) => Person { def apply(name: String, age: Int) = new Person def unapply(p: Person): Option((String, Int)) = Some((p.name, p.age))
  65. 65. Partial functions trait Function1[T, R] { def apply(x: T): R } trait PartialFunction[T, R] extends Function1[T, R] { def isDefinedAt(x: T): Boolean } List(1,3,5,7) collect { case n if n < 5 => n + 1 } val pf = new PartialFunction[Int, Int] { def apply(x: Int): Int = x match { case n if n < 5 => n + 1 } def isDefinedAt(x: Int): Boolean = x match { case n if n < 5 => true; case _ => false } }
  66. 66. 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(r) }
  67. 67. 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 }

×