0

我希望能够做到这一点:

(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)

将输入转换为字符串,然后转换为符号是行不通的——我可能有传入的形式,而不仅仅是原子。

我确定我在这里遗漏了一些东西。:-)

4

3 回答 3

4

这将产生您想要的扩展:

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

...但是这样的宏不太可能真的是您在更高级别上想要的(除非您只想玩宏)。扩展不是有效的列表形式,因此使用它的唯一方法是调用您MACROEXPAND自己。如果你要调用MACROEXPAND,为什么不把它变成一个函数并调用那个函数呢?

于 2013-01-31T08:43:17.970 回答
3

如果要将 item 转换为 form (quote item),则必须提供转换。

例如(list 'quote item)

`(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))

但现在它不知道该怎么办(quoter some-variable)。现在你不能转换一个列表——因为它是未知的。现在您需要提供一个宏扩展,它将在运行时进行转换......

于 2013-01-31T13:26:52.787 回答
2

单线是:

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

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

于 2013-03-25T09:52:06.540 回答