2017-06-10 97 views
0

這是關於「彙編和宏擴展」主題的引用,來自Common Lisp: A gentle introduction to symbolic computation這本書。彙編和宏

(defmacro bad-announce-macro() 
(format t "~%Hi mom!")) 
(defun say-hi() 
(bad-announce-macro)) 
> (compile 'say-hi) 
Hi, mom! 
SAY-HI 
> (say-hi) 
NIL 

在上面的例子宏被擴展爲 編譯SAY-HI的過程的一部分。所以編譯器說‘‘Hi, mom!’’宏 的結果是NIL,所以這就是編譯到SAY-HI的主體。當我們將 稱爲已編譯的SAY-HI函數時,它沒有說明什麼,因爲宏已將其 替換爲其擴展。


在這種行情中,作者說

宏已被替換成其擴展

好了,所以它不應該ATLEAST顯示印刷"Hi mom!"?因爲雖然宏不返回任何東西,但它仍然被某些東西取代(它是擴展)。根據代碼,我假設在編譯函數後調用函數時,所有在其正文中調用的宏都會展開爲結果,它們返回,而不是它們在其自己的主體中擁有的任何宏。

我不確定這是否正確。做這件事的原因也不清楚。

+1

宏的擴展是宏的返回值。由於宏返回'NIL',所以它的擴展是'NIL',這就是它在'SAY-HI'函數中被替換的原因。 – jkiiski

+0

@jkiiski:但是爲什麼函數會打印'「喂媽媽!」'直到它沒有被編譯? – Mooncrater

+1

編譯代碼時會擴展宏(擴展期間宏的副作用發生)。在此之前,它的解釋代碼(並且在調用函數時,宏將隨時擴展),無論您使用的是什麼實現。 – jkiiski

回答

2

未指定宏展開的頻率。

在LispWorks解釋型的Lisp:

CL-USER 49 > (say-hi) 

Hi mom! 
Hi mom! 
NIL 

宏擴展在運行時在這裏做兩次。

在編譯代碼中,我們期望在運行時不需要宏擴展。因此,在你的例子沒有將要打印的,因爲生成的代碼不執行任何操作:

CL-USER 50 > (compile 'say-hi) 

Hi mom! 
SAY-HI 
NIL 
NIL 

CL-USER 51 > (say-hi) 
NIL 

宏擴展NIL

CL-USER 52 > (macroexpand '(bad-announce-macro)) 

Hi mom! 
NIL  ; <- the macro expansion 
T