Scala meetup - Milan, 25 May 2013
Computational reflection is a mechanism that permits to do computations on
the computation itself. Scala before version 2.10 was relying on the Java
implementation for all the reflective computations but this has some
limitations especially on the support of types proper of Scala. In Scala
2.10 reflection becomes a native concept and covers the whole spectrum of
Scala concepts; it also introduces some specific reflective mechanisms as
macros. In this talk, we will explore what reflection is, why it is a
desirable mechanism for modern programming languages and to what extent and
how Scala 2.10 supports it.
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
Reflection in Scala Whats, Whys and Hows - Walter Cazzola (Dipartimento di Informatica - Università degli Studi di Milano)
1. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 1 of 22
Reflection in Scala 2.10+
Whats, Whys and Hows
Walter Cazzola
Dipartimento di Informatica
Università degli Studi di Milano
e-mail: cazzola@di.unimi.it
2. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 2 of 22
Computational Reflection.
General Definitions.
Computational reflection can be intuitively defined as:
cthe activity done by a SW system to represent and
manipulate its own structure and behaviord. [1]
The reflective activity is done analogously to the usual system
activity.
[1] D. Bobrow, R. G. Gabriel and J. L. White. CLOS in Context.
In OOP: the CLOS Perspective. MIT Press, 1993.
3. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 3 of 22
Computational Reflection.
Characterization of a Reflective System.
Structural and Behavioral Reflection
– the behavioral reflection allows the program of monitoring and
manipulating its own computation;
– the structural reflection allows the program of inspecting and al-
tering its own structure
Introspection and Intercession.
– introspection permits to observe the structure and behavior of
the application, whereas
– intercession permits to alter its structure and behavior
4. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 3 of 22
Computational Reflection.
Characterization of a Reflective System.
Structural and Behavioral Reflection
– the behavioral reflection allows the program of monitoring and
manipulating its own computation;
– the structural reflection allows the program of inspecting and al-
tering its own structure
Introspection and Intercession.
– introspection permits to observe the structure and behavior of
the application, whereas
– intercession permits to alter its structure and behavior
When the meta-level entities exist:
– compile-time: the causal connection is implicit, base-level and meta-
levels are merged together during a preprocessing phase;
– load-time: in this case the causal connection behaves as in the case,
reflection takes place at compile-time.
– run-time: the causal connection is explicit and must be maintained
by an entities super-parties, e.g., by the virtual machine or by the
run-time environment;
5. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 4 of 22
Computational Reflection.
Es. To Enrich the Behavior of a Method Call.
Each method call is logged into a file.
Hello logMeta
doLog()
doInvoke()
logMeta
hello
sayHello() invoke(sayHello)
meta
meta
6. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 4 of 22
Computational Reflection.
Es. To Enrich the Behavior of a Method Call.
Each method call is logged into a file.
Hello logMeta
doLog()
doInvoke()
logMeta
hello
sayHello() invoke(sayHello)
meta
meta
sayHello()
7. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 4 of 22
Computational Reflection.
Es. To Enrich the Behavior of a Method Call.
Each method call is logged into a file.
Hello logMeta
doLog()
doInvoke()
logMeta
hello
sayHello() invoke(sayHello)
meta
metainvoke()
sayHello()
8. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 4 of 22
Computational Reflection.
Es. To Enrich the Behavior of a Method Call.
Each method call is logged into a file.
¯
logFile
Hello logMeta
doLog()
doInvoke()
logMeta
hello
sayHello() invoke(sayHello)
meta
doLog()
metainvoke()
sayHello()
Method sayHello on Hello object
9. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 4 of 22
Computational Reflection.
Es. To Enrich the Behavior of a Method Call.
Each method call is logged into a file.
¯
logFile
console
Hello logMeta
doLog()
doInvoke()
logMeta
hello
sayHello() invoke(sayHello)
meta
doLog()
metainvoke()
sayHello()
doInvoke()
Method sayHello on Hello object
Hello World!!!
10. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 5 of 22
Scala Reflection.
The Java Case.
Java provides reflection via the java.lang.reflection library
– pretty good for introspection activities but
– quite limited on intercession (only behavioral manipulation)
Scala <2.10 inherits reflection from Java.
11. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 5 of 22
Scala Reflection.
The Java Case.
Java provides reflection via the java.lang.reflection library
– pretty good for introspection activities but
– quite limited on intercession (only behavioral manipulation)
Scala <2.10 inherits reflection from Java.
So why should we need an ad hoc implementation?
12. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 5 of 22
Scala Reflection.
The Java Case.
Java provides reflection via the java.lang.reflection library
– pretty good for introspection activities but
– quite limited on intercession (only behavioral manipulation)
Scala <2.10 inherits reflection from Java.
So why should we need an ad hoc implementation?
– some types are wrongly reified due to type erasure
scala> case class A[T]
scala> println(A[String].isInstanceOf[A[String]])
true
scala> println(A[String].isInstanceOf[A[Int]])
true
– the whole spectrum of types, modifiers and constructs is not cov-
ered (e.g., implicit, path dependent and abstract types)
– limited intercession, no structural reflection at all.
13. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 6 of 22
Reflection in Scala
Core Data Structures
Who can access to the necessary data?
14. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 6 of 22
Reflection in Scala
Core Data Structures
Who can access to the necessary data? The compiler.
Trees, Symbols and Types
[17:52]cazzola@surtur:~>scalac -Xshow-phases
phase name id description
---------- -- -----------
parser 1 parse source into ASTs, perform simple desugaring
namer 2 resolve names, attach symbols to named trees
typer 4 the meat and potatoes: type the trees
pickler 8 serialize symbol tables
Reflection in Scala regards
– ASTs and types
– all the information about them can be provided by the compiler
These are just few out the 30 phases the compiler performs.
15. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 7 of 22
Scala Reflection
-Yshow-trees
object Test {
println("Hello World!")
}
[18:05]cazzola@surtur:~>scalac -Xprint:parser -Yshow-trees helloworld.scala
[[syntax trees at end of parser]] // Scala source: helloworld.scala
PackageDef(
"<empty>"
ModuleDef(0 "Test"
Template("scala"."AnyRef" // parents
ValDef(private "_" <tpt> <empty>)
DefDef(0 "<init>" [] List(Nil) <tpt>
Block(
Apply(
super."<init>"
Nil
)()
)
)
Apply(
"println"
"Hello World!"
)
)
)
)
17. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 9 of 22
Reflection in Scala
Summary of the Trees
Trees are created naked by Parser.
Both definitions and references (expressed as ASTs) get their
symbols filled in by Namer (tree.symbol).
When creating symbols, Namer also creates their completers,
lazy thunks that know how to populate symbol types (symbol.info).
Typer inspects trees, uses their symbols to transform trees and
assign types to them (tree.tpe).
Shortly afterwards Pickler kicks in and serializes reachable sym-
bols along with their types into ScalaSignature annotations.
18. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 10 of 22
Scala Reflection
Universes & Mirrors
Universes are environments that pack together trees, symbols
and their types.
– Compiler (scala.tools.nsc.Global) is a universe.
– Reflection runtime (scala.reflect.runtime.universe) is a universe
too.
– Macro context (scala.reflect.macros.Context) holds a reference
to a universe.
19. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 10 of 22
Scala Reflection
Universes & Mirrors
Universes are environments that pack together trees, symbols
and their types.
– Compiler (scala.tools.nsc.Global) is a universe.
– Reflection runtime (scala.reflect.runtime.universe) is a universe
too.
– Macro context (scala.reflect.macros.Context) holds a reference
to a universe.
Mirrors abstract population of symbol tables.
Each universe can have multiple mirrors, which can share symbols
with each other within their parent universe.
– Compiler loads symbols from pickles using its own *.class parser. It
has only one mirror, the rootMirror.
– Reflective mirror uses Java reflection to load and parse ScalaSigna-
tures. Every classloader corresponds to its own mirror created
with ru.runtimeMirror(classloader).
– Macro context refers to the compiler’s symbol table.
20. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 11 of 22
Scala Reflection
Entry Points
Using a universe depends on your scenario.
– You can play with compiler’s universe (aka global) in REPL’s :power
mode.
– With runtime reflection you typically go through the Mirror in-
terface, e.g. scala.reflect.runtime.currentMirror, then cm.reflect
and then you can get/set fields, invoke methods, etc.
– In a macro context, you import c.universe._ and can use imported
factories to create trees and types (avoid to create symbols).
21. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 11 of 22
Scala Reflection
Entry Points
Using a universe depends on your scenario.
– You can play with compiler’s universe (aka global) in REPL’s :power
mode.
– With runtime reflection you typically go through the Mirror in-
terface, e.g. scala.reflect.runtime.currentMirror, then cm.reflect
and then you can get/set fields, invoke methods, etc.
– In a macro context, you import c.universe._ and can use imported
factories to create trees and types (avoid to create symbols).
All universe artifacts are path-dependent on their universe.
scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}
scala> ru.reify(2.toString)
res1: reflect.runtime.universe.Expr[String] = Expr[String](2.toString())
With runtime reflection, there is only one universe.
With macros it is more complicated. To pass artifacts around is
necessary to piggyback the universe as well.
22. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 12 of 22
Scala Reflection
Inspect Members
scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}
scala> trait X { def foo: String }
defined trait X
23. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 12 of 22
Scala Reflection
Inspect Members
scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}
scala> trait X { def foo: String }
defined trait X
scala> ru.typeOf[X]
res0: reflect.runtime.universe.Type = X
25. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 13 of 22
Scala Reflection
Analyze and Invoke Members
Get the type, the constructor and its parameters
scala> case class Person(name: String, age: Int)
defined class Person
scala> val personType = typeOf[Person]
personType: reflect.runtime.universe.Type = Person
26. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 13 of 22
Scala Reflection
Analyze and Invoke Members
Get the type, the constructor and its parameters
scala> case class Person(name: String, age: Int)
defined class Person
scala> val personType = typeOf[Person]
personType: reflect.runtime.universe.Type = Person
scala> val ctor = personType.member(nme.CONSTRUCTOR)
ctor: reflect.runtime.universe.Symbol = constructor Person
scala> val args = ctor.asMethod.paramss.head map {p => (p.name.decoded, p.typeSignature)}
args: List[(String, reflect.runtime.universe.Type)] = List((name,String), (age,scala.Int))
27. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 13 of 22
Scala Reflection
Analyze and Invoke Members
Get the type, the constructor and its parameters
scala> case class Person(name: String, age: Int)
defined class Person
scala> val personType = typeOf[Person]
personType: reflect.runtime.universe.Type = Person
scala> val ctor = personType.member(nme.CONSTRUCTOR)
ctor: reflect.runtime.universe.Symbol = constructor Person
scala> val args = ctor.asMethod.paramss.head map {p => (p.name.decoded, p.typeSignature)}
args: List[(String, reflect.runtime.universe.Type)] = List((name,String), (age,scala.Int))
Create a new instance (via the mirror)
scala> val classMirror = currentMirror.reflectClass(personType.typeSymbol.asClass)
classMirror: reflect.runtime.universe.ClassMirror = class mirror for Person
scala> val ctor = personType.declaration(nme.CONSTRUCTOR).asMethod
ctor: reflect.runtime.universe.MethodSymbol = constructor Person
scala> classMirror.reflectConstructor(ctor).apply("Joe", 73)
res1: Any = Person(Joe,73)
28. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 14 of 22
Scala Reflection
Defeat Type Erasure
The compiler implements the type erasure
scala> case class A[T]
scala> println(A[String].isInstanceOf[A[String]])
true
scala> println(A[String].isInstanceOf[A[Int]])
true
29. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 14 of 22
Scala Reflection
Defeat Type Erasure
The compiler implements the type erasure
scala> case class A[T]
scala> println(A[String].isInstanceOf[A[String]])
true
scala> println(A[String].isInstanceOf[A[Int]])
true
Solution: to pass through the reflective TypeTag
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> case class B[T: TypeTag] { val tpe = typeOf[T] }
defined class B
30. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 14 of 22
Scala Reflection
Defeat Type Erasure
The compiler implements the type erasure
scala> case class A[T]
scala> println(A[String].isInstanceOf[A[String]])
true
scala> println(A[String].isInstanceOf[A[Int]])
true
Solution: to pass through the reflective TypeTag
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> case class B[T: TypeTag] { val tpe = typeOf[T] }
defined class B
scala> println(B[String].tpe == typeOf[String])
true
scala> println(B[String].tpe == typeOf[Int])
false
31. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 14 of 22
Scala Reflection
Defeat Type Erasure
The compiler implements the type erasure
scala> case class A[T]
scala> println(A[String].isInstanceOf[A[String]])
true
scala> println(A[String].isInstanceOf[A[Int]])
true
Solution: to pass through the reflective TypeTag
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> case class B[T: TypeTag] { val tpe = typeOf[T] }
defined class B
scala> println(B[String].tpe == typeOf[String])
true
scala> println(B[String].tpe == typeOf[Int])
false
scala> println(B[List[String]].tpe == typeOf[List[String]])
true
scala> println(B[List[String]].tpe == typeOf[List[Int]])
false
32. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 15 of 22
Scala Reflection
Compilation at Run-Time
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> import scala.tools.reflect.ToolBox
import scala.tools.reflect.ToolBox
scala> val tree = Apply(
Select(Literal(Constant(40)), newTermName("$plus")), List(Literal(Constant(2))))
tree: reflect.runtime.universe.Apply = 40.$plus(2)
scala> val cm = scala.reflect.runtime.universe.runtimeMirror(getClass.getClassLoader)
cm: reflect.runtime.universe.Mirror = JavaMirror with ...
scala> println(cm.mkToolBox().eval(tree))
42
Toolbox is a full-fledged compiler.
– Unlike the regular compiler, it uses Java reflection encapsulated in
the provided mirror to populate its symbol table.
– Toolbox wraps the input AST, sets its phase to Namer (skipping
Parser) and performs the compilation into an in-memory directory.
– After the compilation is finished, toolbox fires up a classloader that
loads and lauches the code.
33. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 16 of 22
Scala Reflection
Compile-Time Reflection or Structural Reflection
Macro
It is a pattern or a rule that specifies how a given input se-
quence should be mapped into another.
34. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 16 of 22
Scala Reflection
Compile-Time Reflection or Structural Reflection
Macro
It is a pattern or a rule that specifies how a given input se-
quence should be mapped into another.
. . . but what is a macro, really?
A regular scala function that transforms an AST into another
AST and it is called by the compiler.
35. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 16 of 22
Scala Reflection
Compile-Time Reflection or Structural Reflection
Macro
It is a pattern or a rule that specifies how a given input se-
quence should be mapped into another.
. . . but what is a macro, really?
A regular scala function that transforms an AST into another
AST and it is called by the compiler.
E.g.,
if (1 ==1) { true } else { false }
36. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 16 of 22
Scala Reflection
Compile-Time Reflection or Structural Reflection
Macro
It is a pattern or a rule that specifies how a given input se-
quence should be mapped into another.
. . . but what is a macro, really?
A regular scala function that transforms an AST into another
AST and it is called by the compiler.
E.g.,
if (1 ==1) { true } else { false }
if (1.$eq$eq(1)) { true } else { false }
37. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 17 of 22
Scala Reflection
Abstract Syntax Tree (AST)
if (1.$eq$eq(1)) {true} else {false}
If
Apply
Select
Literal
1
"$eq$eq"
List
Literal
1
Literal
true
Literal
false
38. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 18 of 22
Scala Reflection
Applications of the Macros
Macros permits to transform an AST into a new AST at com-
pile time.
. . . but what we can do wth that?
E.g.,
– zero-overhead assertions, logging or bounds checking;
– static loops unroll or other kind of optimization; or
– static DSL transformation
39. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 19 of 22
Scala Reflection
Macros in Action
import scala.language.experimental.macros
import scala.reflect.macros.Context
import scala.collection.mutable.{ListBuffer, Stack}
object Macros {
def printf(format: String, params: Any*): Unit = macro printf_impl
def printf_impl(c:Context)(format:c.Expr[String], params:c.Expr[Any]*):c.Expr[Unit]={
import c.universe._
val Literal(Constant(s_format: String)) = format.tree
val evals = ListBuffer[ValDef]()
def precompute(value: Tree, tpe: Type): Ident = {
val freshName = newTermName(c.fresh("eval$"))
evals += ValDef(Modifiers(), freshName, TypeTree(tpe), value)
Ident(freshName)
}
val paramsStack = Stack[Tree]((params map (_.tree)): _*)
val refs = s_format.split("(?<=%[w%])|(?=%[w%])") map {
case "%d" => precompute(paramsStack.pop, typeOf[Int])
case "%s" => precompute(paramsStack.pop, typeOf[String])
case "%%" => Literal(Constant("%"))
case part => Literal(Constant(part))
}
val stats = evals ++ refs.map(ref => reify(print(c.Expr[Any](ref).splice)).tree)
c.Expr[Unit](Block(stats.toList, Literal(Constant(()))))
}
}
40. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 20 of 22
Scala Reflection
Macros in Action
object Test extends App {
import Macros._
printf("hello %s!", "world")
}
[22:18]cazzola@surtur:~>scalac Macros.scala
[22:19]cazzola@surtur:~>scalac Test.scala
[22:20]cazzola@surtur:~>scala Test
hello world!
Note that,
– macros must be compiled separately from where they should used,
i.e., no recursive macros are possible;
– macros work on compile time information, i.e., they reify, manipulate
and return an AST.
41. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 21 of 22
Scala Reflection
Conclusions
In Scala 2.10+ you can have all the information about your pro-
gram that the compiler has (well, almost).
– this includes trees, symbols and types and more.
– you can reflect at run-time (scala.reflect.runtime.universe) or at
compile-time (macros).
42. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 21 of 22
Scala Reflection
Conclusions
In Scala 2.10+ you can have all the information about your pro-
gram that the compiler has (well, almost).
– this includes trees, symbols and types and more.
– you can reflect at run-time (scala.reflect.runtime.universe) or at
compile-time (macros).
But (Devil’s Advocate) . . .
– we are still far from C++ Template Programming, e.g., no factorial
at compile time.
– Java reflection, even if limited, is easier to use.
43. Reflection in
Scala 2.10+
Walter Cazzola
Reflection
introduction
properties
example
Scala Reflection
trees
universes
examples
Macros
References
Slide 22 of 22
References
Martin Odersky.
Reflection and Compilers.
Keynote at Lang.NEXT, April 2012.
Eugene Burmako.
Macros.
Scala 2.10 documentation, École Polytechnique Fédérale de Lausanne,
2013.
Heather Miller, Eugene Burmako, and Philipp Haller.
Scala Reflection 2.10.
Scala 2.10 documentation, École Polytechnique Fédérale de Lausanne,
2013.