2010-09-20 89 views
3

請幫忙。我正在嘗試創建這個Lisp宏,它將一個(數字)列表作爲輸入並返回這些數字的總和。代碼基本Lisp宏問題

(setf g (list 1 2 3 4)) 



(defmacro add-test(var) 

    `(+ ,@var)) 

(附加測試克)給出該錯誤

*****的值G型LIST的不。 *****

[類型TYPE-ERROR的條件]在同一時間(附加試驗(1 2 3 4))給出正確的結果是10。

可以請你解釋,爲什麼變量傳遞給函數時不工作?

其他細節 -

Lispbox - SBCL

提前

回答

8

這很容易和最常見的宏觀經濟問題一個Ubuntu Linux操作系統

感謝。

(add-test g) 

現在的宏擴展,宏ADD-TEST被調用時所獲得的價值G,符號參數VAR

然後你嘗試一個列表操作。反引號表達

`(+ ,@var) 

VAR值爲G,並嘗試該拼接到列表(+ ...)。現在返回的表達式是(+ . G)

CL-USER 12 > (macroexpand '(add-test g)) 
(+ . G) 
T 

(+ . G)不是有效的Lisp表單。這不是有效的源代碼。

請記住,宏的參數是未經評估的源表達式。

相比之下,與以下內容:

CL-USER 13 > (macroexpand '(add-test (1 2 3 4))) 
(+ 1 2 3 4) 
T 

你說:「能否請您解釋一下,爲什麼當變量的函數傳遞它不工作?」請注意,ADD-TEST不是一個函數,它是一個宏。一個宏獲得源代碼傳遞並返回一個新的表單 - 然後對該表單進行評估。

+0

感謝Rainer的詳細解答。這有很大幫助。 – bdev 2010-09-20 21:44:01

+0

出於好奇,讓我們說我們進一步採取bdev的想法。假設我有一些可優化的表達式(一個整數列表!),我想在「運行時間」之前優化表達式。我會怎麼做? (儘管我認爲(eval G)可能會奏效......)。 – 2010-09-20 22:22:56

+2

@保羅·納森:你可以EVAL它,編譯它,FUNCALL它,應用它 - 幾乎沒有限制。另請參閱DEFINE-COMPILER-MACRO,它允許您編寫優化。 – 2010-09-20 22:49:03