Common lisp 以编程方式引用(例如,对于宏)

Common lisp 以编程方式引用(例如,对于宏),common-lisp,macrodef,Common Lisp,Macrodef,我希望能够做到这一点: (mapcar #'quote '(1 2 3 4)) 还有这个 ('1'2'3'4) 然而,由于QUOTE是一种特殊的形式,它不能被调用 我试着将其放大: (defmacro quoter (&rest args) `(loop for arg in ,@args collect (quote arg))) (quoter '(1 2 3 4 )) 但这让我明白了,正如我所料 (LOOP FOR ARG IN '(1 2 3 4) COLL

我希望能够做到这一点:

(mapcar #'quote '(1 2 3 4))
还有这个

('1'2'3'4)

然而,由于QUOTE是一种特殊的形式,它不能被调用

我试着将其放大:

(defmacro quoter (&rest args)
  `(loop for arg in ,@args collect (quote arg)))

(quoter '(1 2 3 4 ))
但这让我明白了,正如我所料

(LOOP FOR ARG IN '(1 2 3 4)
      COLLECT 'ARG)
将输入转换为字符串,然后再转换为符号是行不通的——我可能有传入的表单,而不仅仅是原子


我肯定我遗漏了一些东西。:-)

这将产生您想要的扩展:

(defmacro quoter (&rest args)
   (loop for arg in args collect `(quote ,arg)))

…但这样的宏不太可能是您在更高级别上真正想要的(除非您只想玩宏)。扩展不是有效的列表表单,因此使用它的唯一方法是自己调用
MACROEXPAND
。如果要调用
MACROEXPAND
,为什么不将其设置为函数并调用该函数?

如果要将项转换为表单
(引用项)
,则必须提供转换

例如
(列表'报价项)

`(quote ,item)
如果在函数中使用特殊窗体或宏,则可以使用该函数并将其传递给类似于
MAPCAR
的对象

CL-USER > (mapcar #'(lambda (item) (list 'quote item)) '(1 2 3 4))

((QUOTE 1) (QUOTE 2) (QUOTE 3) (QUOTE 4))
如果列表被替换为变量,也可以这样做

如果你想把它写成宏,那么你会遇到一个问题,那就是你需要转换源代码。如果您有一个列表,那么您可以直接转换它。例如,如果您有一个变量,那么您就不能(因为您不知道这个变量的值),并且您必须将转换包含到生成的源中

例如:

CL-USER 119 > (defmacro quoter (list)
                (list 'quote (mapcar (lambda (item) (list 'quote item))
                                     (second list))))
QUOTER

CL-USER 120 > (macroexpand '(quoter '(1 2 3 4)))
(QUOTE ((QUOTE 1) (QUOTE 2) (QUOTE 3) (QUOTE 4)))
T

CL-USER 121 > (quoter '(1 2 3 4))
((QUOTE 1) (QUOTE 2) (QUOTE 3) (QUOTE 4))

但现在它不知道如何处理
(引用一些变量)
。现在您无法转换列表,因为它是未知的。现在,您需要提供一个宏扩展,它将在运行时对转换进行扩展…

这方面的一个要点是:

(mapcar (lambda (x) `',x) '(1 2 3 4))

注意引号的用法。我发现这个表单有时很有用。

我主要是在玩宏。:-)其动机是,我实际上是想看看我是否可以用CommonLisp编写一个fexpr工具,只是为了好玩。:-)@PaulNathan,Common Lisp提供了编译器宏,这可能是不必编写自己的代码遍历程序就可以得到的最接近的宏。