2017-05-08 109 views
1

http://www.gigamonkeys.com/book/practical-a-simple-database.html「 @」在LISP宏函數

的,@‘拼接’以下表達式的值 - 其必須 評估到列表 - 進入封裝列表。您可以在以下兩個表達式間看到 差異,而且,@:

`(and ,(list 1 2 3)) ==> (AND (1 2 3)) 

`(and ,@(list 1 2 3)) ==> (AND 1 2 3) 

即使有例子,我不能收集,@做什麼。有人可以明確提到第二個例子中的步驟嗎? (是,這裏口齒不清初學者)

+0

你能詳細說明你不理解什麼嗎?你可以看到,在一種情況下,你仍然有parens,而在另一種情況下,你不會。你可以把',@'想象成只是在最後一步運行一個額外的步驟,它從列表中刪除了零部件。你已經明白'\''和','做什麼了嗎? –

+0

僅僅是'@'刪除列表?我想我明白什麼是反引用和','這樣做。 Backquote =不會被評估。逗號=將被評估。對? –

+0

是的,你對反引號和逗號是正確的。嚴格地說,我認爲',@'實際上做的是添加'。 '。你可以看到這個,如果你做',@'的東西不是一個列表。問題是'''告訴lisp明確地把一些東西放在cons單元中。但是,在cons單元中添加一個列表只會擴展當前列表。基本上,它「清理」了清單。而不是使用AND作爲第一個元素,第二個元素是嵌套列表1 2 3,因爲1 2 3已添加到包含AND的一個元素列表中,所以最終只有一個列表。 –

回答

3

這裏是您的示例的略加修改:

`(foo bar ,(list 1 2 3) baz) ==> (foo bar (1 2 3) baz) 

`(foo bar ,@(list 1 2 3) baz) ==> (foo bar 1 2 3 baz) 

在第一個表達式列表(1 2 3)插入作爲在結果列表中的一個元素。在第二個表達式中,列表(1 2 3)的元素成爲結果列表中的元素。這些清單是「拼接」的。

2

請注意,反引號功能獨立於。這是一個通用機制,可以從模板構建列表。由於Lisp源代碼基於列表,因此從源代碼模板構建Lisp源代碼有時也很有用。

CL-USER 86 > `(one pi ,(* 1 pi) 
       two pi ,(* 2 pi)  
       three pi ,(* 3 pi)) 
(ONE PI 3.141592653589793D0 
TWO PI 6.283185307179586D0 
THREE PI 9.42477796076938D0) 

CL-USER 87 > `((one pi ,(* 1 pi)) 
       (two pi ,(* 2 pi)) 
       (three pi ,(* 3 pi))) 
((ONE PI 3.141592653589793D0) 
(TWO PI 6.283185307179586D0) 
(THREE PI 9.42477796076938D0)) 


CL-USER 90 > `(((one pi) (two pi) (three pi)) 
       ,(loop for i from 1 upto 3 collect (list (* pi i)))) 
(((ONE PI) (TWO PI) (THREE PI)) 
((3.141592653589793D0) (6.283185307179586D0) (9.42477796076938D0))) 

在這裏與,@,其中結果列表在剪接的示例。其結果列表消失及其元件成爲生成的列表的成員。

CL-USER 91 > `(((one pi) (two pi) (three pi)) 
       ,@(loop for i from 1 upto 3 collect (list (* pi i)))) 
(((ONE PI) (TWO PI) (THREE PI)) 
    (3.141592653589793D0) (6.283185307179586D0) (9.42477796076938D0))