Find file
Fetching contributors…
Cannot retrieve contributors at this time
563 lines (417 sloc) 11.4 KB

What's new in Scala 2.10

!SLIDE intro

Scala 2.10!

Adriaan Moors | @adriaanm | Typesafe

!SLIDE left

Hi!

  • Thank you, contributors!
  • Some numbers
    • Mailing list members: >4K
    • Issue tracker
      • >3K registered users (2K not on mailing list)
      • >7K reported issues
        • top-11: 25%, top-55: 50%, top-1100: 95%
      • 5 issues/day
    • GitHub
      • Close 6 PR/day

!SLIDE

Scala

Simple

!SLIDE

Scala

I'm serious

!SLIDE

Scala

simple != easy

!SLIDE

Scala = Unifier

  • Functions (small abstractions)
  • Objects and traits (big abstractions)

!SLIDE

Scala = Unifier

  • Experimentation
  • Large-scala^He development

!SLIDE left

Simplicity

  • Simple core: objects and methods
  • Simple reduction into core
    • (x: Int) => x ~> new {def apply(x: Int) = x}
    • for comprehensions
    • pattern matching
    • string interpolation
    • context bounds

!SLIDE left

Experimenting

Queue demo effect

println("")

!SLIDE top

Behind the scenes

import unfiltered.netty.websockets._

val sockets = ListBuffer.empty[WebSocket]
WebSocketServer("/socket/repl", 8080) {
  case Open(s) => sockets += s
  case Message(s, Text(str)) =>
    val resp = interpret(str)
    sockets foreach (_.send(resp))
} run ()

!SLIDE top

Behind the scenes

val interpreter = new IMain(settings)
val completion  = new JLineCompletion(interpreter)

def interpret(data: String): String = {
  data.split(":", 2) match {
    case Array("run", source) =>
      util.stringFromStream { ostream =>
        Console.withOut(ostream) {
          interpreter.interpret(source) } }
    case Array(r"""complete@(\d*)${I(pos)}""", source) =>
      // handle completion at position $pos
  }
}

github.com/adriaanm/replhtml

github.com/adriaanm/talks

!SLIDE

To be continued

!SLIDE left

Scala 2.10 highlights

  • Rewritten Pattern Matcher
  • String Interpolation (SIP-11)
  • Value Classes (SIP-15)
  • Implicit Classes (SIP-13)

!SLIDE left

Scala 2.10 highlights

  • Feature Imports (SIP-18)
  • Futures and Promises (SIP-14)
  • Dependent method types
    • Cake factory methods
  • ASM-based back-end <!-- (faster, adds basic 1.6/1.7 support) -->

!SLIDE left

Scala 2.10 highlights

!SLIDE left

Pattern matcher

!SLIDE left

Pattern matcher

New and improved

  • Extractors can be extension methods
  • Nicer error messages via SAT solving
    • Improving CNF encoding: #2724
  • "Virtualized": e.g., match in the probability monad

!SLIDE

Exhausting

def check(x: Option[String]) = x match {
  case Some("magic") =>
}

!NOTES case Some(_) => case None =>

check(None)

!SLIDE left

Scala = Unifier

  • Extractors reconcile
    • Pattern matching
    • OO Encapsulation
  • Requires Option boxing
    • @paulp's tackling this in 2.11
    • Value classes meet patmat

!SLIDE

Extractors

object I {
  def unapply(x: String) = util.Try { x.toInt } toOption
}

"10" match { case I(10) => }

I.unapply("10") match { case Some(10) => }

(New in 2.10: Try, based on Twitter's com.twitter.util.)

!NOTES import language.postfixOps

!SLIDE

String interpolation

def bottles(n: String)       = s"$n bottles of beer"

def safeBottles(n: Int)      = f"$n%d bottles of beer"

def brokenBottles(n: Double) = f"$n%d bottles of beer"

!NOTES this is the unifier of the talk implicit classes value classes string interpolators patmat & objects macros (printf-style validation)

!SLIDE left

String interpolation

  1. drop $-prefixed holes
  2. pack parts in a StringContext
  3. call the interpolator (named in the prefix)
  4. pass the holes as arguments

!SLIDE

Desugaring interpol

// def bottles(n: String) = s"$n bottles of beer"
def bottles(n: String) = StringContext("", " bottles of beer").s(n)

Somewhere, in the standard library:

case class StringContext(parts: String*) {
  def s(args: Any*): String = standardInterpolator(treatEscapes, args)
}

!SLIDE

Interpol & macros

Where'd my StringContext go?

// def safeBottles(n: Int) = f"$n%d bottles of beer"
def safeBottles(n: Int) = "%d bottles of beer" format n

There's a macro for that.

case class StringContext(parts: String*) {
  // check that types, number of `args` correspond to formatter in `parts`
  def f(args: Any*): String = macro macro_StringInterpolation_f
}

!SLIDE

Interpol & patmat

And now... in reverse!?

"10 bottles" match {
  case r"""\d* bottles""" => "ok!"
}

Can this work?

!SLIDE

Interpol & patmat

Sure, let's dissect

val Pattern = r"""\d* bottles"""

"10 bottles" match {
  case Pattern() => "ok!"
}
  • Interpolated strings are first-class.
  • No need to first put it in a val.
    • Uniformity ~> simplicity
  • If we can make this work, so will the original

!SLIDE

Interpol & patmat

Desugaring the extractor

val Pattern = r"""\d* bottles"""

Pattern.unapplySeq("10 bottles") match {
  case Some(_) => "ok!"
}
  • unapplySeq generalizes unapply
    to variable number of subpatterns

!SLIDE

Interpol & patmat

Desugaring interpol

val Pattern = StringContext("""\d* bottles""").r

Pattern.unapplySeq("10 bottles") match {
  case Some(_) => "ok!"
}

!NOTES

"10 bottles" match {
 case r"""(\d*)${I(x)} bottles""" => x
}

Problem reduced

  • add method def r: X to StringContext
  • X must have an unapplySeq method

!SLIDE

implicit meets class

implicit class RContext(sc: StringContext) {
 def r = new util.matching.Regex(
    sc.parts.mkString(""), 
    sc.parts.tail.map(_ => "x"): _*
  )
}
  • implicit class encapsulates
    best practice implicit conversions
  • before, only implicit val or def
    • y no implicit class!?

!SLIDE left

Scala = Unifier

  • Type inference
  • Value inference (implicit val)
  • Here be (cool) dragons
    • specs, shapeless, scalaz,...
    • [paper] fighting bitrot with types
    • [paper] type classes as objects and implicits

!SLIDE

Interpol & patmat

implicit class RContext(sc: StringContext) {
 def r = new util.matching.Regex(
    sc.parts.mkString(""), 
    sc.parts.tail.map(_ => "x"): _*
  )
}

val n = "10 bottles" match { 
 case r"""(\d*)$n bottles""" => n 
}

!SLIDE

Supreme thrift

val r"""(\d*)${I(n)} bottles""" = "10 bottles"

Note: n is an Int!

!SLIDE

Interpol & patmat

Cool applications/articles:

!SLIDE left

Scala = Pragmatic

  • Balance
    • Java interop
    • Legacy
    • Desire for new toys
  • With
    • Make programming fun
    • Sanity
    • Simplicity

!SLIDE

Scala = Pragmatic

  • Immutable / pure encouraged.
  • Mutation / impure where you need it.

!SLIDE

Asynch meets Mutation

Because we can

import concurrent._; import ExecutionContext.Implicits.global

var y = 0

Future { y = 1 } ; Future { y = 2 }

doesn't mean you should

(this generalizes)

!SLIDE

Asynchronicity

Futures

def slowCalcFuture: Future[Int] = ...
val future1 = slowCalcFuture
val future2 = slowCalcFuture
def combined: Future[Int] = for {
  r1 <- future1
  r2 <- future2
} yield r1 + r2

!SLIDE

Asynchronicity

scala-async!

def combined: Future[Int] = async {
  val future1 = slowCalcFuture
  val future2 = slowCalcFuture
  await(future1) + await(future2)
}

!SLIDE

Types are there for you

  • Future[T] vs T
    • important difference
    • Future[T] keeps latency,
      error handling on your mind

!SLIDE left

import language._

SIP-18 helps you KISS

  • Help you identify Good Parts for
    • your project, and
    • your team,
    • at this time.
  • Desirable subset of Scala evolves.

!SLIDE

import language._

  • postfixOps
  • reflectiveCalls
  • implicitConversions
  • existentials
  • higherKinds
  • dynamics
  • experimental.macros

!SLIDE

Dynamic

class AnythingGoes extends Dynamic {
  def applyDynamic(selection: String)(args: Any*): Any =
    println(s"You called $selection${args.mkString("(", ",", ")")}. Thanks!")
}

!NOTES import language.dynamics (new AnythingGoes).notInspired("sorry")

!SLIDE

Dynamic meets macro

By @paulp

scala> val dict = Dict.dict
dict: Dict = Dict(88629 words, 103040 definitions)

// safe, unsafe, it's all the same if we know what we're doing
scala> dict.unsafeOracle.flibbertigibbet
res1: Definitions = 
flibbertigibbet
Flib"ber*ti*gib`bet, n.Defn: An imp. Shak.

scala> dict.safeOracle.flibbertigibbet
res2: Definitions = 
flibbertigibbet
Flib"ber*ti*gib`bet, n.Defn: An imp. Shak.

!SLIDE

Dynamic meets macro

By @paulp

// it is when we make up supposed "crazy, made-up" words that we
// enjoy the difference
scala> dict.unsafeOracle.bippy
res3: Definitions = Runtime Vocabulary Failure: No Such Word

scala> dict.safeOracle.bippy
:9: error: not found: "bippy"
              dict.safeOracle.bippy
                   ^

typesafe proxy https://gist.github.com/paulp/5265030

!SLIDE left

Scala 2.11

Smaller

  • Modularizing std lib & compiler
  • Roll your own scala.xml!

!SLIDE left

Scala 2.11

Faster

  • Incremental compiler
    (@gkossakowski)
  • Better optimizer/codegen
    (@magarciaEPFL, @jamesiry)

!SLIDE left

Scala 2.11

Stabler

  • Mature 2.10's experimental features
  • Macros & Reflection
    • stay experimental, no type macros
    • best practices: blackbox macros

!SLIDE

Thanks!

Questions!