【问题标题】:&optional parameter in lisp macros: Why does this variable behave like this?lisp 宏中的 &optional 参数:为什么这个变量的行为是这样的?
【发布时间】:2017-03-03 14:19:14
【问题描述】:

我正在尝试创建一个具有 &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 >

我不太明白为什么宏在第二种情况下不能使用默认值。有没有更好的方法来编写这个代码或者至少是一种解决方法?

谢谢,

【问题讨论】:

    标签: macros lisp common-lisp


    【解决方案1】:

    什么

    您需要引用默认参数值:

    (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
    

    现在您可以看到错误的来源:您没有引用参数的默认值,因此它被计算了两次。

    【讨论】:

      猜你喜欢
      • 2020-08-22
      • 2019-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-02-13
      • 2013-11-02
      • 1970-01-01
      相关资源
      最近更新 更多