Macros Lisp-在宏中使用逗号(`,`)

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)) ; ==>

我正在用Elisp练习编写宏。老师建议我们在“Quasikote”中加入程序的宏观部分

我想编写一个宏“printCdrEach”,打印列表中cdr的每个元素(只是为了练习)

我一直收到错误“无效函数:2”。我确信编译器认为
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
  • 表达式
    (2 3 4)
    无效。在REPL中尝试一下,您会得到
    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