Pau*_*des 3 lisp macros common-lisp
我正在尝试创建一个具有&optional默认值参数的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 >
Run Code Online (Sandbox Code Playgroud)
我不太明白为什么宏在第二种情况下不能使用默认值.是否有更好的方法来编写此代码或至少是一种解决方法?
谢谢,
您需要引用默认参数值:
(defmacro test-lambda-1 (f &optional (tableau 'table1))
`(list ,f ,tableau))
(test-lambda-1 0)
==> (0 ((1 2 3) (4 5 6)))
Run Code Online (Sandbox Code Playgroud)
您需要考虑Common Lisp如何评估您的代码:当它看到时(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
Run Code Online (Sandbox Code Playgroud)
现在您可以看到错误的来源:您没有引用参数的默认值,因此它被评估了两次.
| 归档时间: |
|
| 查看次数: |
149 次 |
| 最近记录: |