user=> (macroexpand '(when (pos? a) (println "positive") (/ b a)))
(if (pos? a) (do (println "positive") (/ b a)))
Clojureは、ユーザーコードによってコンパイラを拡張できる、プログラム的なマクロシステムを備えています。マクロを使用すると、他の言語ではプリミティブまたは組み込みサポートが必要となる構文構造を定義できます。Clojureの多くのコア構造は、実際にはプリミティブではなく、通常のマクロです。
user=> (macroexpand '(when (pos? a) (println "positive") (/ b a)))
(if (pos? a) (do (println "positive") (/ b a)))
他のマクロは、->
マクロのように、各式を次の式の最初の引数として再帰的に挿入するなど、便利な方法でフォームを再配置します。
user=> (-> {} (assoc :a 1) (assoc :b 2))
{:b 2, :a 1}
user=> (macroexpand '(-> {} (assoc :a 1) (assoc :b 2)))
(assoc (assoc {} :a 1) :b 2)
より高度な使用方法のために、defmacro 内で 2 つの特殊変数を使用できます。
&form
- 呼び出されている実際のフォーム(データとして)
&env
- マクロ展開時点でのローカルバインディングのマップ。 env マップは、シンボルから、そのバインディングに関するコンパイラ情報を保持するオブジェクトへのマップです。
以下のマクロはすべてAPIページに記載されています。多くは、注記されているトピックページでも説明されています。
マクロの作成: defmacro definline macroexpand-1 macroexpand
分岐: and or when when-not when-let when-first if-not if-let cond condp
ループ(シーケンスも参照): for doseq dotimes while
変数の操作(変数と環境も参照): ns declare defn defmacro definline defmethod defmulti defn- defonce defstruct
コードの異なる配置: .. doto ->
動的スコープ(変数と環境も参照): binding locking time with-in-str with-local-vars with-open with-out-str with-precision
遅延評価のものの作成(シーケンスも参照): lazy-seq lazy-cat delay
Java相互運用マクロ: .. amap areduce gen-class gen-interface proxy proxy-super memfn
コードのドキュメント化: assert comment doc
トランザクション: dosync io!