アナフォリックマクロ
Programming ClojureのChapter 7 Macroの途中まで読んだので、マクロを使ってみた。
アナフォリックマクロを作成しようとして、
sample/macro.clj
(ns sample.macro) (defmacro aif [pred then] `(let [it ~pred] (if it ~then)))
を定義し、実行すると、
user> (use 'sample.macro) nil user> (aif (+ 1 2 3) (println it)) ; Evaluation aborted. Can't let qualified name: sample.macro/it [Thrown class java.lang.Exception]
エラーとなる。
Clojureでは、マクロ展開時のシンボル補足によるバグを防ぐため、「`」でクオートされた構文中にシンボルが表われた場合は、そのシンボルはqualified nameになる。
上記の aifの場合は、it は sample.macro/it となるため、エラーとなる。
user> (macroexpand '(aif (+ 1 2 3) (println it))) (let* [sample.macro/it (+ 1 2 3)] (if sample.macro/it (println it)))
アナフォリックマクロのように、シンボル補足を利用するマクロの場合は、補足したいシンボルに~'を付ければ良い。
(defmacro aif ([pred then] `(aif ~pred ~then nil)) ([pred then else] `(let [~'it ~pred] (if ~'it ~then ~else))))
user> (aif (+ 1 2 3) (println it)) 6 nil user> (aif false (println it) (println it)) false nil
動いた。\(^▽^)/