99re热这里只有精品视频,7777色鬼xxxx欧美色妇,国产成人精品一区二三区在线观看,内射爽无广熟女亚洲,精品人妻av一区二区三区

clojure macros

2018-02-24 15:18 更新

X分鐘速成Y

其中 Y=clojure macros

源代碼下載:?learnclojuremacros-zh.clj

和所有Lisp一樣,Clojure內(nèi)在的同構(gòu)性使得你可以窮盡語言的特性,編寫生成代碼的子過程——“宏”。宏是一種按需調(diào)制語言的強(qiáng)大方式。

小心!可以用函數(shù)完成的事用宏去實(shí)現(xiàn)可不是什么好事。你應(yīng)該僅在需要控制參數(shù)是否或者何時(shí)eval的時(shí)候使用宏。

你應(yīng)該熟悉Clojure.確保你了解Y分鐘學(xué)Clojure中的所有內(nèi)容。

;; 使用defmacro定義宏。宏應(yīng)該輸出一個(gè)可以作為clojure代碼演算的列表。
;;
;; 以下宏的效果和直接寫(reverse "Hello World")一致。

(defmacro my-first-macro []
  (list reverse "Hello World"))

;; 使用macroexpand或macroexpand-1查看宏的結(jié)果。
;;
;; 注意,調(diào)用需要引用。
(macroexpand '(my-first-macro))
;; -> (#<core$reverse clojure.core$reverse@xxxxxxxx> "Hello World")

;; 你可以直接eval macroexpand的結(jié)果
(eval (macroexpand '(my-first-macro)))
; -> (\d \l \o \r \W \space \o \l \l \e \H)

;; 不過一般使用以下形式,更簡短,更像函數(shù):
(my-first-macro)  ; -> (\d \l \o \r \W \space \o \l \l \e \H)

;; 創(chuàng)建宏的時(shí)候可以使用更簡短的引用形式來創(chuàng)建列表
(defmacro my-first-quoted-macro []
  '(reverse "Hello World"))

(macroexpand '(my-first-quoted-macro))
;; -> (reverse "Hello World")
;; 注意reverse不再是一個(gè)函數(shù)對象,而是一個(gè)符號(hào)。

;; 宏可以傳入?yún)?shù)。
(defmacro inc2 [arg]
  (list + 2 arg))

(inc2 2) ; -> 4

;; 不過,如果你嘗試配合使用引用列表,會(huì)導(dǎo)致錯(cuò)誤,
;; 因?yàn)閰?shù)也會(huì)被引用。
;; 為了避免這個(gè)問題,clojure提供了引用宏的另一種方式:`
;; 在`之內(nèi),你可以使用~獲得外圈作用域的變量。
(defmacro inc2-quoted [arg]
  `(+ 2 ~arg))

(inc2-quoted 2)

;; 你可以使用通常的析構(gòu)參數(shù)。用~@展開列表中的變量。
(defmacro unless [arg & body]
  `(if (not ~arg)
     (do ~@body))) ; 別忘了 do!

(macroexpand '(unless true (reverse "Hello World")))

;; ->
;; (if (clojure.core/not true) (do (reverse "Hello World")))

;; 當(dāng)?shù)谝粋€(gè)參數(shù)為假時(shí),(unless)會(huì)演算、返回主體。 
;; 否則返回nil。

(unless true "Hello") ; -> nil
(unless false "Hello") ; -> "Hello"

;; 需要小心,宏會(huì)搞亂你的變量
(defmacro define-x []
  '(do
     (def x 2)
     (list x)))

(def x 4)
(define-x) ; -> (2)
(list x) ; -> (2)

;; 使用gensym來獲得獨(dú)有的標(biāo)識(shí)符
(gensym 'x) ; -> x1281 (or some such thing)

(defmacro define-x-safely []
  (let [sym (gensym 'x)]
    `(do
       (def ~sym 2)
       (list ~sym))))

(def x 4)
(define-x-safely) ; -> (2)
(list x) ; -> (4)

;; 你可以在 ` 中使用 # 為每個(gè)符號(hào)自動(dòng)生成gensym
(defmacro define-x-hygenically []
  `(do
     (def x# 2)
     (list x#)))

(def x 4)
(define-x-hygenically) ; -> (2)
(list x) ; -> (4)

;; 通常會(huì)配合宏使用幫助函數(shù)。
;; 讓我們創(chuàng)建一些幫助函數(shù)來支持(無聊的)算術(shù)語法:

(declare inline-2-helper)
(defn clean-arg [arg]
  (if (seq? arg)
    (inline-2-helper arg)
    arg))

(defn apply-arg
  "Given args [x (+ y)], return (+ x y)"
  [val [op arg]]
  (list op val (clean-arg arg)))

(defn inline-2-helper
  [[arg1 & ops-and-args]]
  (let [ops (partition 2 ops-and-args)]
    (reduce apply-arg (clean-arg arg1) ops)))

;; 在創(chuàng)建宏前,我們可以先測試
(inline-2-helper '(a + (b - 2) - (c * 5))) ; -> (- (+ a (- b 2)) (* c 5))

; 然而,如果我們希望它在編譯期執(zhí)行,就需要?jiǎng)?chuàng)建宏
(defmacro inline-2 [form]
  (inline-2-helper form)))

(macroexpand '(inline-2 (1 + (3 / 2) - (1 / 2) + 1)))
; -> (+ (- (+ 1 (/ 3 2)) (/ 1 2)) 1)

(inline-2 (1 + (3 / 2) - (1 / 2) + 1))
; -> 3 (事實(shí)上,結(jié)果是3N, 因?yàn)閿?shù)字被轉(zhuǎn)化為帶/的有理分?jǐn)?shù))

擴(kuò)展閱讀

Clojure for the Brave and True系列的編寫宏 http://www.braveclojure.com/writing-macros/

官方文檔 http://clojure.org/macros

何時(shí)使用宏? http://dunsmor.com/lisp/onlisp/onlisp_12.html

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)