Macros Lisp-在宏中使用逗号(`,`)
我正在用Elisp练习编写宏。老师建议我们在“Quasikote”中加入程序的宏观部分 我想编写一个宏“printCdrEach”,打印列表中cdr的每个元素(只是为了练习) 我一直收到错误“无效函数:2”。我确信编译器认为Macros Lisp-在宏中使用逗号(`,`),macros,lisp,elisp,Macros,Lisp,Elisp,我正在用Elisp练习编写宏。老师建议我们在“Quasikote”中加入程序的宏观部分 我想编写一个宏“printCdrEach”,打印列表中cdr的每个元素(只是为了练习) 我一直收到错误“无效函数:2”。我确信编译器认为2是一个函数。然而,我不知道如何修复这个程序 在不更改输入格式的情况下(printCdrEach x x x),在我的程序中如何正确使用“,”使其工作?您应该尝试宏扩展-1: (macroexpand-1 '(print-cdr-each 1 2 3 4)) ; ==>
2
是一个函数。然而,我不知道如何修复这个程序
在不更改输入格式的情况下(printCdrEach x x x),在我的程序中如何正确使用“,”使其工作?您应该尝试
宏扩展-1
:
(macroexpand-1 '(print-cdr-each 1 2 3 4))
; ==> (while (not (null (2 3 4)))
; (eval (car (2 3 4)))
; (setq rest (cdr (2 3 4))))
; ==> t
- 表达式
无效。在REPL中尝试一下,您会得到(2 3 4)
eval:1不是函数名
- 您多次使用
,因此,如果它是一个表达式,则会对其求值不止一次rest
(defun for-each (operation &rest elements)
(loop :for e :in elements
:do (funcall operation e)))
(for-each #'print 10 20)
10
20
; ==> nil
宏是语法糖。这意味着你应该能说什么
(每个打印cdr 1 2 3 4)
应扩展到代码内。由于您是以宏的形式执行此操作,因此可能需要将其扩展为静态:
(defmacro for-each (operation &rest elements)
`(progn ,@(loop :for e :in elements
:collect `(,operation ,e))))
(macroexpand-1 '(for-each print a b))
; ==> (progn (print a) (print b))
; ==> t
(let ((a 10) (b 20)) (for-each print a b))
10
20
; ==> 20
为什么这是一个宏?宏编写的第一条规则是:当函数足够时不要编写宏。第二条规则可能是:除非必须使用,否则不要使用
eval
,你可能不会。此外,在lisps:lispers care;)中,更喜欢kebab盒
而不是camelCase
)是的,这就是为什么我说这只是为了练习语法,因为我是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))
可能是朝着正确方向迈出的一步。这个问题基于elisp,而我认为你的答案是CL。elisp确实有,而。不确定是否有花式的循环(我打赌有一个包…)。
(defmacro for-each (operation &rest elements)
`(progn ,@(loop :for e :in elements
:collect `(,operation ,e))))
(macroexpand-1 '(for-each print a b))
; ==> (progn (print a) (print b))
; ==> t
(let ((a 10) (b 20)) (for-each print a b))
10
20
; ==> 20