3. LES MACROS ET MOI
2012 : [ScalaDays London] “S’il n’y a rien de nouveau
dans Scala, je vais finir par faire du Clojure …” ->
MaKro
2013 : “Atelier : Dans S’cas là”, utilisation des macros
pour augmenter les tests unitaires.
!
2014 : Type providers ? So 2008
!
4. QU’EST CE QU’UNE MACRO ?
• Une
macro est une “méthode” définie par l’utilisateur qui est
appelée lors de la compilation.
• En
Scala on a les def macro.
6. CLOJURE - DEMO !
(defn ifp [pred thenf elsef]
"if in point fix style (= ((ifp even? inc dec) 2) 3)"
(fn [a] (if (pred a) (thenf a) (elsef a))))
(defn reverse-at [n col]
"(= (reverse-at 2 [1 2 3]) [2 1 3])"
(let [[part1 part2] (split-at n col)]
(concat (reverse part1) part2)))
!
(defmacro infix [form]
(clojure.walk/postwalk (ifp seq? (partial reverse-at 2) identity) form))
!
;; (1 + 2) est une forme infix, normalement en Clojure on écrit :
;; (+ 1 2)
(def e (quote (infix ((+ partial 1) map [(1 + (2 * 3)) (2 - 3)]))))
!
(eval e)
;=> (8 0) ; List(8,0)
(macroexpand e)
;=> (map (partial + 1) [(+ 1 (* 2 3)) (- 2 3)])
;; c’est “l’AST” qui va être exécuté après l’expansion des macros
7. !
!
Expr(
Block(
List(
ValDef(
Modifiers()
, newTermName("a")
, TypeTree()
, Literal(Constant(2))
)
, ValDef(
Modifiers()
, newTermName("b")
, TypeTree()
, Literal(Constant(3))
)
)
, Apply(
Select(Ident(newTermName("a"))
, newTermName("$plus"))
, List(Ident(newTermName("b"))))
)
)
L’AST SCALA
{
val a = 2
val b = 3
a + b
}
8. UN PEU PLUS INTERACTIF
!
!
On peut inspecter les expressions dans une session de REPL avec les
commandes suivantes :
!
> import scala.reflect.runtime.{universe => u}
!
> u.showRaw( u.reify {{ val a = 2 ; val b = 3 ; a+b }})
!
(showRaw ne suffit pas parfois
!
scalac -Xplugin macro-paradise_2.10.2-2.0.0-SNAPSHOT.jar deprecation -Xprint:parser -Ystop-after:parser -Yshow-trees-compact
*.scala
!
)
!