深入瞭解lisp(clojure)-宏

來源:互聯網
上載者:User

本文由larrylgq編寫,轉載請註明出處:http://blog.csdn.net/larrylgq/article/details/7395261

作者:呂桂強

郵箱:larry.lv.word@gmail.com

lisp使用特殊操作符來擴充文法,但是在lisp中特殊操作符的數量是固定的,為瞭解決這個問題lisp引入了宏,宏並不直接做事,而是產生實際的業務代碼。

宏的求值過程:接收S-運算式為參數,返回一個lisp展開式(ecpansion),對該展開式求值。

編譯過程:在clojure中使用compile編譯源檔案的時候,將檔案中所有宏遞迴展開成展開式,此時代碼中只有函數調用形式和特殊形式。將展開後的代碼編譯成FASL檔案,使用LOAD函數載入時會執行這些編譯過的代碼。

由於宏不會被直接求值的特性,所以我們定義的宏可以不是標準格式的lisp,每個宏都可以定義自己的文法。

相較於使用核心加上標準庫的方式定義的語言,lisp可以通過宏來定義新的文法,並將它放在標準庫裡,而不是寫入程式碼在語言核心。

當然你也可以將自己會大量複用的代碼抽象成宏來使代碼更簡潔。

 

宏的結構:名字+形參列表+可選文檔字串+聲明+lisp運算式體

一個簡單的例子,使用宏實現

(defmacro while  "Repeatedly executes body while test expression is true. Presumes  some side-effect will cause test to become false/nil. Returns nil"  {:added "1.0"}  [test & body]  `(loop []     (when ~test       ~@body       (recur))))

當我們這樣調用的時候:

user=> (def a (atom 10))                                #'user/auser=> (while (pos? @a) (do (println @a) (swap! a dec)))

將會在編譯器產生如下代碼:

(defn while [(pos? a) (do (println @a) (swap! a dec))]

(loop [] (

 (when (pos? a)

  (do (println @a) (swap! a dec))

  (recur)

)

)))

符號使用:

反引號 :防止宏體內的運算式被evaluate。

波浪號:使用在在反引號裡面,它的值會被替換。

~@: 替換某個具體元素。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.