Clojure

巨集

目錄

Clojure 有一個程式化巨集系統,讓編譯器可以透過使用者程式碼進行擴充。巨集可以用來定義語法結構,在其他語言中需要使用原語或內建支援才能做到。事實上,Clojure 的許多核心結構並非原語,而是常規巨集。

有些巨集會產生原語形式的簡單組合。例如,when 會結合 ifdo

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 中有兩個特殊變數可供更進階的用法

  • &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!

一些 特殊形式 實際上是作為巨集實作的,主要是為了提供解構: fn let loop