【发布时间】:2021-05-27 21:12:48
【问题描述】:
我正在练习用 Elisp 编写宏。老师建议我们将程序的宏部分包含在“quasiquote”中。
我想写一个宏“printCdrEach”来打印列表中cdr的每个元素(只是为了练习)
(defmacro print-cdr-each (first &rest rest)
`(while (not (null ,rest))
(eval (car ,rest))
(setq rest (cdr ,rest)))
)
(print-cdr-each 1 2 3 4) ; Expected Output 2 3 4
我不断收到错误“无效函数:2”。我确信编译器认为2 是一个函数。但是,我不确定如何修复此程序。
在不更改输入格式 (printCdrEach x x x x) 的情况下,在我的程序中正确使用“,”以使其正常工作?
【问题讨论】:
-
为什么这是一个宏?宏编写的第一条规则是:当函数足够时不要编写宏。可能第二条规则是:除非必须,否则不要使用
eval,而且您可能不需要。另外,在 lisps 中更喜欢kebab-case到camelCase:lispers care ;) -
是的,这就是为什么我说它只是为了练习语法,因为我是 Lisp 新手,所以我想开始一些简单的事情。值得注意的是,我不知道 Lisp 中的这种命名约定。谢谢指出
-
另外,如果我不使用
eval,我将如何在这里打印出元素? (rest的car)是错误的根源来自我使用eval的事实吗? -
(2 3 4) 将代替 ,rest,因此 (car ,rest) 将评估为 2,并且 (eval 2) 不起作用,因为 2 不是函数,因此出现错误信息。您不想使用打印功能代替 eval 吗?
-
@JayK --
(eval 2)工作正常,因为eval评估表单。这是错误的做法。(car ,rest)-->(car (2 3 4))和(2 3 4)尝试使用参数3和4调用函数2。相反,(car (quote ,rest))可能是朝着正确方向迈出的一步。