lisp 裡的 ,@ 反引號 的解釋

babyyellow發表於2012-08-23
剛接觸lisp 的童鞋,看到宏程式碼的時候,基本都會遇到這個問題哈。


【,@】  【】 中間包括的那倆個符號代表啥意思? 會鬱悶很久的。



解釋在這裡:


反引號 (Backquote)

反引號讀取宏 (read-macro)使得從模版 (templates)建構列表變得有可能。反引號廣泛使用在宏定義中。一個平常的引用是鍵盤上的右引號 (apostrophe),然而一個反引號是一個左引號。(譯註: open quote 左引號,closed quote 右引號)。它稱作“反引號”是因為它看起來像是反過來的引號 (titled backwards)。

(譯註: 反引號是鍵盤左上方數字 1 左邊那個: ` ,而引號是 enter 左邊那個 ')

一個反引號單獨使用時,等於普通的引號:

> `(a b c)
(A B C)

和普通引號一樣,單一個反引號保護其引數被求值。

反引號的優點是,在一個反引號表示式裡,你可以使用 , (逗號)與 ,@ (comma-at)來重啟求值。如果你在反引號表示式裡,在某個東西前面加逗號,則它會被求值。所以我們可以使用反引號與逗號來建構列表模版:

> (setf a 1 b 2)
2
> `(a is ,a and b is ,b)
(A IS 1 AND B IS 2)

透過使用反引號取代呼叫 list ,我們可以寫出宏會產生出的展開式的宏定義。舉例來說 nil! 可以定義為:

(defmacro nil! (x)
  `(setf ,x nil))

Comma-at 與逗號相似,但將其(本來應該是列表的)引數扒開。將列表的元素插入模版來取代列表。

> (setf lst '(a b c))
(A B C)
> `(lst is ,lst)
(LST IS (A B C))
> `(its elements are ,@lst)
(ITS ELEMENTS ARE A B C)

Comma-at 在宏裡很有用,舉例來說,在用剩餘引數 (rest parameters)表示程式碼主體的宏。假設我們想要一個 while 宏,只要初始測試表示式為真,對其主體求值:

> (let ((x 0))
    (while (< x 10)
       (princ x)
       (incf x)))
0123456789
NIL

我們可以透過使用一個剩餘引數 (rest parameter) ,蒐集主體的表示式列表,來定義一個這樣的宏,接著使用 comma-at 來扒開這個列表放至展開式裡:

(defmacro while (test &rest body)
  `(do ()
       ((not ,test))
     ,@body))




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/133735/viewspace-741742/,如需轉載,請註明出處,否則將追究法律責任。

相關文章