what's a macro?: learning by examples
DESCRIPTION
Since 2.10.0 Scala includes macros. I was talk about something like the following: * What do macros benefit to us? * What can we do with macros? * Actual use casesTRANSCRIPT
What's a macro?Learning by Examples
Takako Shimamoto BizReach, Inc
What to Talk About
• What are macros?
• Good thing about macros
• Actual use cases of macros
• Future of macros
Are you using macros?
If “Yes",
The Fab You!
Because
• Using macros is easy, developing macros is hard
What are macros?
• Code that generates code
• Not textual code generation
What are macros?
• An experimental feature of 2.10+
• Compiler invokes functions
Before macros
• Ad-hoc textual code generation by sbt plugin
• Compile-time AST operation by compiler plugin
Why macros are necessary?
• Code is made simple
• Efficiency improved
Macro is on your side!
To use macros?
• Need to be enabled explicitly
• import scala.language.experimental.macros
• -language:experimental.macros
Notes
• Macros are separate compilation
• Macro implementations need to be compiled before the main compilation
Def Macros
Def Macros
• Def macros replace well-typed terms with other well-typed terms
• Can contain arbitrary Scala constructs
Practical exampleScala Logging
Where?
logger.debug(s"Some $expensive message!")you call
if (logger.isDebugEnabled) logger.debug(s"Some $expensive message!")
replaced by macros
Macro definition• Starts with the conditional keyword macro
• Followed by a static macro implementation method
Implementation of the macro• Takes several parameter lists
Implementation of the macro• Takes several parameter lists
First comes a single parameter, of type
Context
Implementation of the macro• Takes several parameter lists
Next, followed by a list of parameters that have the same names as the macro
definition parameters
Macro definition
Implementation of the macro
• The original macro parameter has
• type T
• A macro implementation parameter has
• type c.Expr[T]
Quasiquotes• q"..." string interpolators that build code
• Unnecessary to directly implement the AST
• To use the quasiquotes from the macro, just write import c.universe._
Quasiquotes• Using the showRaw, it is possible to see the AST
Goodness
• The hard to comprehend notion of meta programming
• def macros are similar to the concept of a typed method call
Practical example
specs2
Where?
• To use macros to automatically generate matchersfor any complex type
• MatcherMacros trait
Where?
case class Cat(name: String, age: Int) !
// your test case val cat = Cat(name = "Tom", age = 2) cat must matchA[Cat].name("Tom")
you call
Where?
def matchACat( name: Matcher[String] = AlwaysMatcher(), age: Matcher[Int] = AlwaysMatcher() ): Matcher[Cat] = name ^^ {(cat: Cat) => cat.name} and age ^^ {(cat: Cat) => cat.age}
replaced by macros
Macro definition• Generics
• Has type parameters
Implementation of the macro• Type tags(actual type arguments) will be passed
along when the macro is expanded
Implementation of the macro• Type tags(actual type arguments) will be passed
along when the macro is expanded
Come with WeakTypeTag context bounds
Goodness
• DRY approach
• Usage is fairly simple
Blackbox vs Whitebox
• From 2.11
• Not implemented in 2.10 or in macro paradise
• in 2.12, only include blackbox macros
Blackbox vs Whitebox
• 2.10
• scala.reflect.macros.Context
• 2.11
• scala.reflect.macros.blackbox.Context
• scala.reflect.macros.whitebox.Context
Why distinction?• Type specification of macro is curious
class Foo class Bar extends Foo !
object FooExample { def foo: Foo = macro foo_impl def foo_impl(c: Context): c.Expr[Foo] = c.Expr[Foo](c.universe.reify(new Bar).tree) }
Scala 2.10
Why distinction?
• Type checking during macro expansion
• Not affect after expansion
scala> FooExample.foo res0: Bar = Bar@4118f8dd
Blackbox restrictions
• Type parameters of macro affect the type of after macro expansion
• When blackbox macro is used, techniques such as Implicit Macros will not work
No restrictions Whitebox
• Same as 2.10 def macros
• Everything that could be done with macros in 2.10 should be possible in 2.11
Practical example
Spire
Appendix - What is Spire?
• A numeric library for Scala
• Using features such as macros, type classes
• Fast and Precise
Where?
• Using string interpolation and macros, Spire provides convenient syntax for number types
• Evaluated at compile-time
Macro definition• As usual
string interpolation
Implementation of the macro• Syntax check at compile-time
Implementation of the macro• Syntax check at compile-time
Occur at compile-time if any errors
encounter
Goodness
• Static (compile-time) type check
• Runtime error decrease
But, has weak side.
Current state• Optimized towards compiler developers, not library
users
Complicated!!
Scala 2.12 (plan)
• Not introduce new features
• Bugfixes and stability improvements
• Mention later why reason…
scala.meta
• A new experimental API for metaprogramming
• Formerly known as Project Palladium
scala.meta
• Implemented in a library shipped separately from the official Scala distribution
• The first milestone release is scheduled for this fall
The goal of scala.meta
• Metaprogramming easy
• New API is going to greatly simplify writing macros
• Not require knowledge of compiler internals
Language model• All represented with trees
Types
NamesModifiers
…
Trees
scala.meta
Terms
Symbols
Language model
• Keeps all the information about the program
• Comments also remain
• No information is lost anymore
Manner of utilization
• Code generation
• Static type checking
• etc…
Summary
• Macros are actively used in the OSS library
• Can be more efficiently and safely programming
• Scala macros are evolving!
Thanks!!