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)))
いくつかのマクロは再帰的に式を次の式の第1引数として挿入する ->
マクロのようにフォームを便利な形に並べ替える:
user=> (-> {} (assoc :a 1) (assoc :b 2))
{:b 2, :a 1}
user=> (macroexpand '(-> {} (assoc :a 1) (assoc :b 2)))
(assoc (clojure.core/-> {} (assoc :a 1)) :b 2)
高度な用法のために、defmacroの中で使用可能な特別な変数が2つある:
&form
- 呼び出される(データとしての)実際のフォーム
&env
-
マクロ展開の時点でのローカル束縛のマップ。envマップはシンボルからオブジェクトへのマップであり、その束縛についてのコンパイラ情報を持つ。
以下のマクロは全て the 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
varを扱う ( Varと環境 も参照):
ns
declare
defn
defmacro
definline
defmethod
defmulti
defn-
defonce
defstruct
コードの並べ替え:
..
doto
->
動的スコープ ( Varと環境 も参照):
binding
locking
time
with-in-str
with-local-vars
with-open
with-out-str
with-precision
lazyなものを作成する ( シーケンス も参照):
lazy-cat
lazy-cons
delay
Javaとの相互運用 macros:
..
amap
areduce
gen-class
gen-interface
proxy
proxy-super
memfn
コードをドキュメント化する:
assert
comment
doc
トランザクション:
dosync
io!
いくつかの 特殊形式 は実際には主に分配束縛を提供する目的でマクロとして実装されている: fn let loop