What's new with Scala 2.10.0? A brief look at the past, and a detailed look at what's coming down the pipeline.
Note: at the time this presentation was created, Scala 2.10.0 had not been released yet. The final version will probably differ in some ways.
Last update: September 20th
1 of 118
More Related Content
Scala 2.10.0 (english version)
1. Where did we came from, and where are we going to?
Daniel Capó Sobral
Last revision: Jan 05, 2013
2. Revision History
Jul 20, 2012: add IsSeqLike and Searching
Aug 08, 2012: removed previous revision – it didn’t
make 2.10.0; added raw interpolator; added :warnings;
renamed makro to macros; @static; scaladoc grouping
and link to anything
Aug 09, 2012: fixed stuff on macros and reflect; fixed
stuff with Try; added references to other presentations
Sep 20, 2012: rescue replaced with recoverWith
Jan 05, 2014: Incorporate feedback about macros;
improve actors; add links to some docs;
3. Who am I?
Daniel C. Sobral @ Stack Overflow
dcsobral @ Twitter, Gmail/Gtalk, Skype, SliderShare
Daniel Sobral @ Facebook, Speaker Deck, LinkedIn
http://www.linkedin.com/in/danielsobral
http://www.slideshare.net/dcsobral
https://speakerdeck.com/u/dcsobral
http://dcsobral.blogspot.com
4. What do I know about Scala?
Scala gold badge @ Stack Overflow
Small contributions to Scala:
code optimization
enhancements
bug fixes
documentation (not that small)
Active member of the Scala community (mailing lists,
irc)
Blog about Scala
5. IMPORTANT!
Scala 2.10.0 has not been released!
At the time this presentation has been written... (July,
07, 2012)
The information that follows may be changed before
2.10.0 is released.
6. Summary
History
Near Future
Versioning
Release Process
Bug fixes
Enhancements
SIPs (Scala Improvement Process)
Reflection
Actors and Akka
Distant Future
9. Some important landmarks
2011
• Parallel Collections
2010
• New Collections Design
• Binary Compatibility of
Minor Releases
2008
• Java Generics
• Case Class Extractors
2007
• Extractors
• Private/protected
primary constructors
• Private[this]
• Placeholder
2006 parameters
• Scalac written in • Early Initialization
Scala • Abstract Type
• Implicits Constructors
• Traits e • Existential Types
linearization • Lazy values
• Structural Types
Not comprehensive, by any means!
• Multilline Strings
12. Versioning – Scala 2.10.0
Major release
Binary incompatible with previous versions
Language changes
Library changes
New deprecations
Removal of deprecated features
Classes
Methods
Language syntax
13. Examples of New Deprecations
Octal numbers!
scala> 077
<console>:1: warning: Treating numbers with a leading zero as octal is
deprecated.
077
^
res10: Int = 63
Double ending in dot
scala> 1.
<console>:1: warning: This lexical syntax is deprecated. From scala
2.11, a dot will
only be considered part of a number if it is immediately followed by
a digit.
1.
^
res11: Double = 1.0
14. Examples of removal of deprecated
features
Language syntax
for ( val i <- 1 to 10) println(i)
Class
scala.collection.mutable.CloneableCollection
Method
scala.collection.immutable.Queue.+
Package
scala.testing.SUnit
15. Improvements of the release
process
Process becoming more and more automated
Package for RPM, APT, Brew, etc
Automatically generated!
Milestones used to help integrate libraries and
frameworks
M4 June 12
M5 soon!
Release Candidates to consolidate and fix bugs
16. Bug fixes
Many fixes!
New pattern matcher!
Ticket priorization!
New warnings:
Detecting bugs in the compiler itself!
More third party contributions!
git + pull request == FTW
...besides the natural improvements of the codebase.
21. New stuff
Type Classes:
Hashing (there’s an Equiv already)
IsTraversableOnce and IsTraversableLike
Try (Twitter’s alternative to Either)
Package scala.util.hashing
Configurable Pools for parallel collections
@static
@unspecialized
to[Collection]
???
22. New compile parameters
override object (-Yoverride-objects)
bytecode version 49, 50 and 51 (-target:jvm-1.x-asm)
-optimize faster and more effective (ok, not new)
-Dscala.timings=true shows what’s is taking so long to
compile
SIP-18: -language:XXX, -feature
various logs
various macro
various patmat
etc
23. New REPL commands
The :warnings command will turn on all hidden
warnings, such as deprecation (that one is going to my
finger’s muscle memory...)
24. scala.util.hashing.Hashing
def hashingOf[T : Hashing](obj: T): Int =
implicitly[Hashing[T]].hash(obj)
// A bad hashing function for Seqs
implicit val seqHashing =
Hashing fromFunction ((_: Seq[_]).size)
25. IsTraversableOnce and
IsTraversableLike
class FilterMapImpl[A, Repr]
(val r: GenTraversableLike[A, Repr]) {
final def filterMap[B, That]
(f: A => Option[B])
(implicit cbf: CanBuildFrom[Repr, B, That])
: That =
r.flatMap(f(_).toSeq)
}
// How to write the implicit conversion???
26. IsTraversableOnce and
IsTraversableLike
Obstacles to writing the implicit conversion:
Array and String are not GenTraversable
String does not have a type parameter (A)
Nor BitSet and other collections
Inference over view bounds is difficult
IsTraversableOnce and IsTraversableLike
provides a solution
27. IsTraversableOnce and
IsTraversableLike
class FilterMapImpl[A, Repr]
(val r: GenTraversableLike[A, Repr]) {
final def filterMap[B, That]
(f: A => Option[B])
(implicit cbf: CanBuildFrom[Repr, B, That])
: That =
r.flatMap(f(_).toSeq)
}
implicit def filterMap[Repr, A](r: Repr)
(implicit fr: IsTraversableOnce[Repr])
: FilterMapImpl[fr.A,Repr] =
new FilterMapImpl(fr.conversion(r))
29. scala.util.Try
Try {
new FileInputStream(a)
} recoverWith {
case _: FileNotFoundException =>
Try(new FileInputStream(b))
} recover {
case _: FileNotFoundException =>
defaultInputStream
} andThen {
stream =>
in = stream.read(); stream.close(); in
}
30. @static
Turn object fields into static fields of the object’s
companion class
Fields are initialized through the static initializer of
the class
Access to these fields are turned into direct static field
access
31. Configurable Pools on Parallel
Collections
import scala.collection.parallel._
val pc = mutable.ParArray(1, 2, 3)
pc.tasksupport = new ForkJoinTaskSupport(
new scala.concurrent.ForkJoinPool(2))
pc map { _ + 1)
pc.tasksupport = new ThreadPoolTaskSupport()
32. Configurable Pools on Parallel
Collections – Customizing
class customTaskSupport extends TaskSupport {
def execute[R, Tp]
(task: Task[R, Tp]): () => R = ???
def executeAndWaitResult[R, Tp]
(task: Task[R, Tp]): R = ???
def parallelismLevel: Int = ???
}
34. ???
??? it‘s a Nothing-returning that throws exceptions
Because it’s type is Nothing, ??? may replace any
expression
Excellent for stubs, exercises and presentations!
35. ???
trait Opt [A] { // Exercise by Tony Morris
def fold[X](some: A => X, none: => X): X = ???
def map[B](f: A => B): Opt[B] = ???
def get: A = ???
def flatMap[B](f: A => Opt[B]): Opt[B] = ???
def mapAgain[B](f: A => B): Opt[B] = ???
def getOrElse(e: => A): A = ???
def filter(p: A => Boolean): Optional[A] = ???
def exists(p: A => Boolean): Boolean = ???
def forall(p: A => Boolean): Boolean = ???
def foreach(f: A => Unit): Unit = ???
def isDefined: Boolean = ???
def orElse(o: => Opt[A]): Opt[A] = ???
// etc
Adapted from Tony Morris, http://blog.tmorris.net/further-understanding-scalaoption/
36. ???
trait Opt [A] { // Exercise by Tony Morris
def fold[X](some: A => X, none: => X): X = ???
def map[B](f: A => B): Opt[B] = ???
def get: A = ???
def flatMap[B](f: A => Opt[B]): Opt[B] = ???
def mapAgain[B](f: A => B): Opt[B] = ???
def getOrElse(e: => A): A = ???
def filter(p: A => Boolean): Optional[A] = ???
def exists(p: A => Boolean): Boolean = ???
def forall(p: A => Boolean): Boolean = ???
def foreach(f: A => Unit): Unit = ???
def isDefined: Boolean = ???
def orElse(o: => Opt[A]): Opt[A] = ???
// etc
Adapted from Tony Morris, http://blog.tmorris.net/further-understanding-scalaoption/
37. Enhancements
Scaladoc
Implicits!
Diagrams!
Link to anything!
Group things!
API docs
Steady stream of improvements on the documents
themselves
See also:
http://docs.scala-lang.org/
41. Scaladoc – Link to anything!
[[x.y.Z.m]] links to m on Z, defaulting to the type Z
if m is present on both type and object
Z! forces type and Z$ forces object, to disambiguate
m can be written with type signature, to disambiguate
[[m]] refers to m on the current scope
If dots or hashes are required in the type signature,
escape them with
42. Scaladoc – Group things!
Scaladoc now has attributes that allow members to be
grouped, and the groups described and prioritized
Members of the same group are displayed together
Groups of lower priority are seen before groups of
higher priorities
See: @group, @groupdesc, @groupname and
@groupprio
43. SIP – Scala Improvement Process
SIP-11: String Interpolation
SIP-12: Uncluttering Scala’s syntax for control
structures
SIP-13: Implicit Classes
SIP-14: Futures and Promises
SIP-15: Value Classes
SIP-16: Self-cleaning Macros
SIP-17: Type Dynamic
SIP-18: Modularizing Language Features
SIP-19: Implicit Source Locations
44. SIP – Scala Improvement Process
SIP-11: String Interpolation (accepted!)
SIP-12: Uncluttering Scala’s syntax for control
structures (postponed)
SIP-13: Implicit Classes (accepted!)
SIP-14: Futures and Promises (accepted!)
SIP-15: Value Classes (accepted!)
SIP-16: Self-cleaning Macros (postponed)
SIP-17: Type Dynamic (accepted!)
SIP-18: Modularizing Language Features (accepted!)
SIP-19: Implicit Source Locations (not accepted)
45. SIP-11: String Interpolation
Lack of string interpolation were a source of constant
complains
Even though very few languages support them!
Odersky says the difference between ${x} and "+x+" is a
single character
If you ignore the shift-typing...
Someone says " and + can be typed without shift on a swiss
keyboard
True!
About-face:
What if string interpolation was more than string
interpolation?
48. SIP-11: String Interpolation:
How does it work?
s"Hello, $name!" // becomes
StringContext("Hello, ", "!").s(name)
f"${ done * 100 / total }%2d% completed" // becomes
StringContext("", "%2d% completed").f(done * 100 / total)
raw"String with n in it"
49. SIP-11: String Interpolation
Multiline literals work too
s"""Ok!"""
Interpolation may be nested
s"${ s"$x" }"
Backslash is not used as escape character
r"d+/$month" // not an actual interpolator!
StringContext("""d+/""").r(month)
But both s and f interpolators add the escaping themselves!
s"Hello, $name!n" // newline normal
But the raw interpolator does not!
How to add/modify behavior:
Enrich My Library on StringContext
Shadowing of object StringContext
Added interpolators don’t actually need to be methods!
50. SIP-11: String Interpolation
// Enrich My Library
class RegexContext(sc: StringContext) {
def r(args: Any*) = {
sc.checkLengths(args: _*)
val res = (args, sc.parts.tail).zipped map {
(arg, part) => s"Q$argE$part"
} mkString ""
(sc.parts.head + res).r
}
}
implicit def toRC(sc: StringContext) = new RegexContext(sc)
52. SIP-11: String Interpolation
// Shadowing of StringContext object
object StringContext(parts: String*) {
def r(args: Any*) = {
require(parts.length == args.length + 1)
val res = (args, parts.tail).zipped map {
"Q" + _ + "E" + _
} mkString ""
(parts.head + res).r }
}
// One can change s and f interpolators!
53. SIP-11: String Interpolation
// apply and unapplySeq
def hello(name: String = "world"): String = i"Hello, $name!"
def who(message: String): String = message match {
case i"Hello, $name!" => name
case _ => “no clue"
}
who(hello("Daniel")) == "Daniel"
54. SIP-11: String Interpolation
// apply and unapplySeq
implicit class SI(sc: StringContext) {
object i {
def apply(args: Any*): String =
sc.parts.head +
(args,sc.parts.tail).zipped.map(_+_).mkString
def unapplySeq(s: String): Option[Seq[String]] = {
val partsr = sc.parts map (p => s"Q$pE")
val r = (partsr mkString "(.*)").r
s match { case r(xs @ _*) => Some(xs) case _ => None }
}
}
}
55. SIP-13: Implicit Classes
“Enrich My Library” (formely “Pimp My Library”) very
popular
But with lots of cerimony...
“Extension methods” becoming common in other
languages (even Java!)
And with less cerimony at that!
Solution: implicit class
57. SIP-14: Futures and Promises
Non-blocking asynchronous of operations is a common
task
Evidence: many libraries have a Future implementation
Including Scala Actors library!
Problem:
Non-standard interface
Interface tied to implementation
Solution:
Powerful and flexible API implementing the concepts of
Future and Promise
58. SIP-14: Futures and Promises
// TODO – Sorry! Examples from SIP:
import scala.concurrent._
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onComplete {
case Right(posts) => for (post <- posts) render(post)
case Left(t) => render("An error has occured: " +
t.getMessage)
}
59. SIP-14: Futures and Promises
// TODO – Sorry! Examples from SIP:
import scala.concurrent._
val f: Future[List[String]] = future {
session.getRecentPosts
}
f onFailure {
case t => render("An error has occured: " + t.getMessage)
} onSuccess {
case posts => for (post <- posts) render(post)
}
60. SIP-14: Futures and Promises
// TODO – Sorry! Examples from SIP:
import scala.concurrent._
def main(args: Array[String]) {
val rateQuote = future {
connection.getCurrentValue(USD)
}
val purchase = rateQuote map {
quote => if (isProfitable(quote)) connection.buy(amount,
quote)
else throw new Exception("not profitable")
}
blocking(purchase, 0 ns)
}
61. SIP-14: Futures and Promises
// TODO – Sorry! Examples from SIP:
import scala.concurrent.{ future, promise }
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()
}
}
62. SIP-15: Value Classes
Curse of references
Curse of boxing:
case class Meter(n: Int) much more “expensive”
than int
Curse of implicit classes:
"abc“.r creates an unnecessary object just to call new
Regex("abc")
We want a class that is not a reference!
Solution: value classes.
63. SIP-15: Value Classes
// String interpolation with implicit value class!
implicit class RegexContext(sc: StringContext) extends AnyVal {
def r(args: Any*) = {
sc.checkLengths(args: _*)
val res = (args, sc.parts.tail).zipped map {
"Q" + _ + "E" + _
} mkString ""
(sc.parts.head + res).r
}
}
64. SIP-15: Value Classes
Can have only one parameter
Which must be a public val
For instance, [T: Ordering](v: T) is not acceptable
Can be extended by traits
If they are either Any or AnyVal
Cannot define equality or hash code
But may be case classes!
Equality and hash code are applied over the parameter
They are effectively “final”
On a local scope, the class is optimized away!
If they escape scope, they are boxed
65. SIP-16: Macros
Acceptance postponed, but available experimentally on
Scala 2.10.0
Large compilers are hard to maintain
Pressure against new features on the compiler
Compiler Plugins can be used to extend Scala...
...but they are difficult to keep in sync with scalac
Possible solution: Macros
“Macros? Ugh!” –C/C++ trauma!
Something new: scala.reflection
Macros become almost free!
66. SIP-16: Macros
Scala CATs!
Compile-time AST Transformations
Abstract Syntax Tree
Inspired by Nemerle macros
Four kind looked into:
Typed def macros – This is the only made available!
Untyped def macros
Type (class/trait) macros
Annotation macros
Official Overview:
http://docs.scala-lang.org/overviews/macros/typemacros.html
67. SIP-16: Macros
// Typed def macros
(1 to 5).foreach(println)
^ ^
| + Type check
+ Macro execution
+ New type check
68. SIP-16: Macros
// Untyped def macros
for {val i = 0; i < 10; i += 1} println(i)
^ ^
| |
| + Arguments not type checked!
+ Macro execution
+ Type check
69. SIP-16: Macros
// Untyped def macros – why?
for {val i = 0; i < 10; i += 1} println(i)
^ ^
| “i” not visible in this scope! +
+ “i” only visible in this scope.
70. SIP-16: Macros
// Type (class/trait) macros
class User extends DbTable(jdbcUrl, “t_user”)
^
+ Macro
// Connects to database at compile time
// and gets table description to create
// class “User”
71. SIP-16: Macros
Type macros are similar to F#’s type providers
Next in line of development
First user likely to be Typesafe’s Slick (formely
ScalaQuery)
http://slick.typesafe.com/
72. SIP-16: Macros
// Macro annotations
@memoize
def fat(n: Int) =
if (n > 0) n * fat(n – 1)
else 1
// Macro applied over the annotated definition,
// be it class, method, parameter, etc
73. SIP-16: Macros
Only typed macros made available...
And with experimental status, at that...
Behind flag –language:experimental.macros...
But already used in some places on the library!
C/C++ macros trauma very widespread...
...but the true C++ macros are templates! (imho)
Macro Paradise used to experiment with other types of
macros:
http://docs.scala-lang.org/overviews/macros/paradise.html
74. SIP-16: Macros
Typed Macros Advantages:
Relatively simple to implement
There’s no difference in the type signature of a method
implemented with a macro!
Easy to test
Hygienic macros provided through a macro!
Therefore, self-cleaning
Non-hygienic Macros are also easy to create
75. SIP-16: Macros
Disadvantages:
Somewhat limited
Two-stages compilation
It’s not possible to define and use a macro on the same
compilation
Non-hygienic by default
Nay-sayers will go on nay-saying.
77. SIP-16: Macros
Path dependent method types:
def m(c: Context)(param: c.Expr[Any]):
c.Expr[Any]
Through –Ydependent-method-types parameter on
previous versions
Reflection, reflection and reflection!
“Once we do reflection right, we get macros for free!” –
paraphrasing Martin Odersky
78. SIP-17: Type Dynamic
Problems:
Scala’s integration to other JVM languages assumes
static typing
Lots of dynamically typed languages on the JVM!
Static typing also hinders some flexible DSLs
Solution: trait Dynamic
Similar to “missing method”
Makes it easy to integrate with other JVM languages
Has great DSL potential
And other uses as well...
79. SIP-17: Type Dynamic
scala> class xmlPath(xml: scala.xml.Node) extends Dynamic {
| def selectDynamic(path: String) = xml path
| }
defined class xmlPath
scala> new xmlPath(<root><a><b><c/></b></a></root>).b
res9: scala.xml.NodeSeq = NodeSeq(<b><c/></b>)
80. SIP-17: Type Dynamic
Method call conversions:
Standard methods:
applyDynamic
Methods with named parameters:
applyDynamicNamed
Setters:
updateDynamic
Getters (nullary methods):
selectDynamic
81. SIP-17: Type Dynamic
Also in the works is DynamicProxy
Add/Change methods, have everything else be
automatically redirected
Might (maybe) even do so with static typing, through
macros!
However, not yet in the library
Might make 2.10.0 or not – time will tell
82. SIP-18: Modularizing Language
Features
Problems:
Some Scala features are hard to understand
Others induce errors
And some are experimental
But they are all necessary, for one reason or another!
Solution: SIP-18
83. SIP-18: Modularizing Language
Features
Controls access to some language features
Using these features cause compilation warnings
Which might become compilation errors in the future
Access to features allowed through:
compile flags
implicit in scope
Access can be allowed through inherited
ScalaDoc explains why control and why make available
84. SIP-18: Modularizing Language
Features
Contentious features:
Postfixed operators
Method invocation made using implicit reflection
Implicit conversions
Higher kinded types
Existentials
Except for those equivalent to Java wildcard types
Type Dynamic
Experimental Features
Macros
85. SIP-18: Modularizing Language
Features
// Postfix operator
scala> "abc" length
warning: there were 1 feature warnings; re-run with -feature for
details
res0: Int = 3
86. SIP-18: Modularizing Language
Features
// Postfix operator, using -feature
scala> "abc" length
<console>:8: warning: postfix operator length should be enabled
by making the implicit value language.postfixOps visible.
This can be achieved by adding the import clause 'import
language.postfixOps'
or by setting the compiler option -language:postfixOps.
See the Scala docs for value scala.language.postfixOps for a
discussion
why the feature should be explicitly enabled.
"abc" length
^
res0: Int = 3
87. SIP-18: Modularizing Language
Features
// Methods called using reflection
scala> val x = new AnyRef { def hello = println("world") }
x: Object{def hello: Unit} = $anon$1@7d628303
scala> x.hello
<console>:10: warning: reflective access of structural type member method hello
should
be enabled
by making the implicit value language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
x.hello
^
world
88. SIP-18: Modularizing Language
Features
// Implicit conversions
scala> implicit def f(s: String): Int = Predef.augmentString(s).toInt
<console>:8: warning: implicit conversion method f should be enabled
by making the implicit value language.implicitConversions visible.
This can be achieved by adding the import clause 'import
language.implicitConversions'
or by setting the compiler option -language:implicitConversions.
See the Scala docs for value scala.language.implicitConversions for a
discussion
why the feature should be explicitly enabled.
implicit def f(s: String): Int = Predef.augmentString(s).toInt
^
f: (s: String)Int
89. SIP-18: Modularizing Language
Features
The feature being limited are implicit conversions
Other implicit usages are still allowed
Implicit conversions through implicit classes works too
90. SIP-18: Modularizing Language
Features
// Higher Kinded Types
scala> class Monad[M[_]]
<console>:9: warning: higher-kinded type should be enabled
by making the implicit value language.higherKinds visible.
This can be achieved by adding the import clause 'import
language.higherKinds'
or by setting the compiler option -language:higherKinds.
See the Scala docs for value scala.language.higherKinds for a
discussion
why the feature should be explicitly enabled.
class Monad[M[_]]
^
defined class Monad
91. SIP-18: Modularizing Language
Features
// Existentials
scala> val l: List[ T forSome { type T }] = List(1)
<console>:7: warning: the existential type T forSome { type T },
which cannot be expressed by wildcards, should be enabled
by making the implicit value language.existentials visible.
This can be achieved by adding the import clause 'import
language.existentials'
or by setting the compiler option -language:existentials.
See the Scala docs for value scala.language.existentials for a
discussion
why the feature should be explicitly enabled.
val l: List[ T forSome { type T }] = List(1)
^
l: List[T forSome { type T }] = List(1)
93. SIP-18: Modularizing Language
Features
// Macros
scala> def g(d: Any): Any = macro f
<console>:12: error: macro definition needs to be enabled
by making the implicit value language.experimental.macros
visible.
This can be achieved by adding the import clause 'import
language.experimental.macros'
or by setting the compiler option -language:experimental.macros.
See the Scala docs for value scala.language.experimental.macros
for a discussion
why the feature needs to be explicitly enabled.
def g(d: Any): Any = macro f
^
94. scala.reflect
Allows us to explore the structure of a program,
and interact with that structure
Wikipedia: reflection happens at compile time
Scala: you use the same API at compile time as well, with
macros
Main Concepts:
Reflection Libraries and Universes
Names, symbols, types and trees
Mirrors
Overview will be provided at:
http://docs.scala-lang.org/overviews/reflection/overview.html
95. scala.reflect – Universes
Source: Scala Reflection Pre-SIP
Notice: all of the classes on scala-library.jar depicted above were removed.
96. scala.reflect – Universes
Contains a number of interrelated elements which,
together, make up the main components of reflection
Symbol
Tree
Name
etc...
Use of path dependent types to relate types with the
universes they came from
97. scala.reflect – Universes
Built in layers with different degrees of detail using the
“cake pattern” :
Base:
Fundamental concepts
Identity, e and little else
JavaUniverse
Manipulation through JVM-provided reflection, enhanced with
information provided by Scala
Macros
Manipulation at compile time
Compiler’s universe, but presented with a more restricted API
Others: compiler
98. scala.reflect – Main Types
Name
FlagSet Symbol
Universe
AnnotationInfo
Type
Position Tree
100. scala.reflect – Name
Scala has two namespaces:
Types
Values (Term)
Name ties a string to one of those namespaces
Name also enables convertion of names from language-
representation to class-file representation
102. scala.reflect – Symbol
All definitions are tied to symbols
Classes
Methods
Parameters
Variables
If you named it, it has a symbol
If you did not name it, but refer to it as being
“anonymous”, it also has a symbol
Immutable at run time
At macro time, one can change its flags
103. scala.reflect – Type
Structure associated with a symbol:
Class members
Parameters and return types of a method
etc
Made up of case classes
Handled through pattern matching
104. scala.reflect – Types and Symbols
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]
scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head
scala> res1.typeSignature
res2: reflect.runtime.universe.Type = => A
scala> res1.typeSignatureIn(res0)
res3: reflect.runtime.universe.Type = => Int
105. scala.reflect – Types and Symbols
def intMethods[T : TypeTag](v: T) = {
val IntType = typeOf[Int]
val vType = typeOf[T]
val methods = vType.members.collect {
case m: MethodSymbol if m.isPublic =>
m -> m.typeSignatureIn(vType)
}
methods collect {
// Pattern-matching various method types:
case (m, mt @ NullaryMethodType(IntType)) => m -> mt
case (m, mt @ MethodType(_, IntType)) => m -> mt
case (m, mt @ PolyType(_, MethodType(_, IntType))) => m -> mt
}
}
106. scala.reflect – Types and Symbols
def intMethods[T : TypeTag](v: T) = {
val IntType = typeOf[Int]
val vType = typeOf[T]
val methods = vType.members.collect {
case m: MethodSymbol if m.isPublic =>
m -> m.typeSignatureIn(vType)
}
methods collect {
// Since m is a MethodSymbol, we can do it like this instead:
case (m, mt) if m.returnType == IntType => m -> mt
}
}
107. scala.reflect – Types and Symbols
def intMethods[T : TypeTag](v: T) = {
val IntType = typeOf[Int]
val vType = typeOf[T]
val methods = vType.members.collect {
case m: MethodSymbol if m.isPublic =>
m -> m.typeSignatureIn(vType)
}
methods collect {
// Actually, you need this to account for type aliases:
case (m, mt) if m.returnType =:= IntType => m -> mt
}
}
108. scala.reflect – Tree
Tree
children
• Tree
• Tree Type Position Symbol
• ...
• Tree
TypTree TermTree
109. scala.reflect – Tree
Compiler’s internal representation of source code
Immutable at runtime, made up of case classes
However, at macro time one can change its symbol, type
and position
Essential when writing macros
Also used for annotated typed
110. scala.reflect – Tree
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> import scala.reflect.runtime.{currentMirror => m}
import scala.reflect.runtime.{currentMirror=>m}
scala> val tb = m.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] =
scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@5bbdee69
scala> val tree = tb.parseExpr("1 to 3 map (_+1)")
tree: tb.u.Tree = 1.to(3).map(((x$1) => x$1.$plus(1)))
scala> val eval = tb.runExpr(tree)
eval: Any = Vector(2, 3, 4)
113. scala.reflect – Mirror
Mirrors allow one to manipulate classes and instances
at run time
Each Universe may have one or mirrors
Each mirror is tied to a class loader
Classes with the same name may be loaded by distinct
class loaders
Mirrors allows reflection over the Scala language,
instead of its JVM implementation
114. scala.reflect – Mirror
val obj = "String"
val objClass = obj.getClass
val classClassLoader = objClass.getClassLoader
val classLoaderMirror = runtimeMirror(classClassLoader)
val classSymbol = classLoaderMirror.classSymbol(objClass)
val classType = classSymbol.typeSignature
val methodName = newTermName("length")
val methodSymbol = classType.member(methodName).asMethodSymbol
val instanceMirror = classLoaderMirror.reflect(obj)
val methodMirror = instanceMirror.reflectMethod(methodSymbol)
methodMirror.apply() // == (obj.length: Any)
115. Actors and Akka
The standard actors library will be removed
Replaced by Akka’s
Akka will be part of 2.10’s distribution
Only binaries – source code will remain apart
The old library will also be available, on a separate jar
There is a migration guide:
http://docs.scala-lang.org/overviews/core/actors-migration-guide.html
The standard actors has a migration kit
This provides a layer over standard and Akka actors to
make them source code compatible with each other
117. Wild Speculations
untyped macros
for { val x = 0; x < 10; x += 1 } println(x)
macro types
class X extends MacroClassY(parm)
macro annotations
@memoize def fat(n: Int) = if (n > 0) n *
fat(n -1) else 1
effect system
abstract types/type parameters unification
pre-processor (DOA!)
118. Other presentations
Alex Boisvert’s Scala Roadmap:
https://speakerdeck.com/u/boia01/p/scala-roadmap-as-
of-april-2012
Goes into much more depth about “distant future”
Simon Ochsenreither’s What’s New in 2.10
http://ochsenreither.posterous.com/whats-new-in-210
No explanations, but more comprehensive, and links to
commits