2017-03-03 57 views
2

我試圖創建一個具有默認值&optional參數的lisp宏。不幸的是,參數的處理方式有所不同,具體取決於它是從默認值還是從提供給宏的參數中讀取。下面的代碼片段重現該問題:&lisp宏中的可選參數:爲什麼此變量的行爲如此?

(setf table1 '((1 2 3) 
       (4 5 6)) 
     table2 '((10 20 30) 
       (40 50 60))) 

(defmacro test-lambda (f &optional (tableau table1)) 
    `(list ,f ,tableau)) 

? (test-lambda 0 table2) ;; This works... 
(0 ((10 20 30) (40 50 60))) 

? (test-lambda 0)   ;; ...but this doesn't 
> Error: Car of ((1 2 3) (4 5 6)) is not a function name or lambda-expression. 
> While executing: CCL::CHEAP-EVAL-IN-ENVIRONMENT, in process listener(1). 
> Type :POP to abort, :R for a list of available restarts. 
> Type :? for other options. 
1 > 

我不太明白爲什麼宏觀不會在第二種情況下,默認值工作。有沒有更好的方法來編碼或至少是一種解決方法?

感謝,

回答

6

什麼

您需要引用,默認參數值:

(defmacro test-lambda-1 (f &optional (tableau 'table1)) 
    `(list ,f ,tableau)) 
(test-lambda-1 0) 
==> (0 ((1 2 3) (4 5 6))) 

爲什麼

你需要考慮how Common Lisp evaluates your code:當它看到(test-lambda ...),它

讓我們試試吧:

(macroexpand '(test-lambda 0)) 
==> (LIST 0 ((1 2 3) (4 5 6))) ; T 
(macroexpand '(test-lambda-1 0)) 
==> (LIST 0 TABLE1) ; T 
(macroexpand '(test-lambda 0 table2)) 
==> (LIST 0 TABLE2) ; T 
(macroexpand '(test-lambda-1 0 table2)) 
==> (LIST 0 TABLE2) ; T 

現在你可以看到那裏的錯誤是來自:你沒有報價參數的默認值,所以它得到了兩次評估。

相關問題