Date post: | 04-Dec-2014 |
Category: |
Technology |
Upload: | nadav-wiener |
View: | 334 times |
Download: | 2 times |
FUN WITH MACROSNadav Wiener
It was Colonel Mustard, in the lounge room, with a rope
sealed trait Suspectcase object MissScarlet extends Suspectcase object ColonelMustard extends Suspectcase object MrsWhite extends Suspectcase object ReverendGreen extends Suspectcase object MrsPeacock extends Suspectcase object ProfessorPlum extends Suspect
The Suspects
The Weapons
sealed trait Weaponcase object Candlestick extends Weaponcase object Dagger extends Weaponcase object LeadPipe extends Weaponcase object Revolver extends Weaponcase object Rope extends Weaponcase object Wrench extends Weapon
The Rooms
sealed trait Roomcase object Kitchen extends Roomcase object Ballroom extends Roomcase object Conservatory extends Roomcase object DiningRoom extends Roomcase object BilliardRoom extends Roomcase object Library extends Roomcase object Lounge extends Roomcase object Hall extends Roomcase object Study extends Room
The Accusation
case class Accusation( suspect: Suspect, room: Room, weapon: Weapon)
BUT NOW WHAT?
Simple answer:val accusation = Accusation( ColonelMustard, Library, LeadPipe)
or build a fancy API
Mixfix notation ⇒ fancy
Example
@syntax def _inThe_withThe_ (suspect: Suspect, room: Room, weapon: Weapon) = Accusation(suspect, room, weapon) !import _inThe_withThe_._!!(ColonelMustard inThe Library withThe LeadPipe) == accusation
@syntax def _inThe_withThe_
(ColonelMustard inThe Library withThe LeadPipe)
Why the awkward name?
@syntax def _inThe_withThe_
(ColonelMustard inThe Library withThe LeadPipe)
the method name is parsed by the macro
MACROS FORMULA1
INTRO
object Cowsay { def cowsay(text: String): String = macro cowsayImpl! def cowsayImpl(c: Context) (text: c.Expr[String]): c.Expr[String] = {! import c.universe._ import sys.process._! val Literal(Constant(input)) = text.tree val output = s"cowsay '$input'"!! c.Expr(q"$output") }}
println(Cowsay.cowsay("use macros!"))
_______________ < 'use macros!' > --------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
_______________ < 'use macros!' > --------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
_______________ < 'use macros!' > --------------- \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
Compiled code keeps working even after removing ‘cowsay’
TYPE PROVIDERS I:MACRO
ANNOTATIONS
Available in 2.10 Macro Paradise
Macro applied using @syntax
class syntax extends StaticAnnotation { def macroTransform(annottees: Any*) = macro Mixfix.impl}
Implemented like other macros
object Mixfix { def impl(c: Context) (annottees: c.Expr[Any]*): c.Expr[Any] = //…}
Enables adding new types and definitions
@syntax def _inThe_withThe_(…) = //…
import _inThe_withThe_._!
TYPE PROVIDERS II: SYNTHETIC
STRUCTURAL TYPES
val foo = new { def bar() = println(3)} !foo.bar()!
Structural type:
Type checked
Use reflection at runtime
Can be generated using 2.10 def macros
Structural types:
ADJECTIVES WITH MACROS
The challenge
Book(true, short, red)
Getting from:
To:
case class Book( interesting: Boolean = false, length: Length = short, color: Color = red)
an (interesting, long, red) Book
mkAdjectives extracts adjectives
Literate initialization for finite fields: boolean, enumeration, case objects
Inspired by E
object Book { val adjectives = Adjectives.mkAdjectives[Book]}import Book.adjectives._!println(an (interesting, long, red) Book)!
THANK YOU
Macro Paradisehttp://docs.scala-lang.org/overviews/macros/paradise.htmlScala Adjectiveshttps://github.com/hunam/scala-adjectivesScala Mixfixhttps://github.com/hunam/scala-mixfix
WE’RE HIRING contact [email protected]