Download - Scala for Jedi
SCALA ДЛЯ ДЖЕДАЕВВладимир Парфиненко
[email protected]@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.")}
string interpolation 2.10
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 implemented2.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
TYPE COVARIANCE
class Cell[+T](x: T) { def get: T = ???} val c1 = new Cell[String]("Anakin")
val c2: Cell[Any] = c1val 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] = c1c2.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] = c1val jedi = c2.get
TYPE COVARIANCE
class Cell[-T](x: T) { def set(x: T) { ??? }} val c1 = new Cell[Any]('Anakin)
val c2: Cell[String] = c1c2.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 BOUNDStrait 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
AnyRef/Object
ScalaObject
Java classesScala classes
Null
Nothing
AnyVal
PrimitivesValue classes2.10
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 COLLECTIONSval nums = (1 to 10).parnums 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
FUTURES 2.10
• Хранилище для значения, которое будет получено в будущем
• Получение значения может быть выполнено асинхронно и не блокировать программу
• Значение может быть не получено вовсе
FUTURESval 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")}
FUTURESval 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, …
PROMISESval 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}
ACTORS & AKKA 2.10
• Акторы – это приватные данные и описание поведения
•Общение между акторами только через сообщения с неизменяемыми данными
• Акторы могут создавать других акторов и управлять ими в случае исключительных ситуаций
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"}
ACTORSclass 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
@tailrec
def find[A](xs
: List[A], p:
(A => Boolean)
): Option[A] =
{
xs match {
case Nil =
> None
case head
:: tail =>
if (p(he
ad)) Some(head
) else find(ta
il, 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.10packa
ge 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>