【问题标题】:Quoting programmatically (i.e., for macros)以编程方式引用(即,用于宏)
【发布时间】:2013-01-31 08:39:00
【问题描述】:

我希望能够做到这一点:

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

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

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

【问题讨论】:

    标签: common-lisp macrodef


    【解决方案1】:

    这将产生你想要的扩展:

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

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

    【讨论】:

    • 我主要是在玩宏。 :-)
    【解决方案2】:

    如果要将项目转换为(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)。现在你不能转换一个列表——因为它是未知的。现在您需要提供一个宏扩展,用于在运行时进行转换...

    【讨论】:

    • 动机是我实际上是想看看我是否可以在 Common Lisp 中编写一个 fexpr 工具,只是为了好玩。 :-)
    • @PaulNathan,Common Lisp 提供了编译器宏,可能是您无需编写自己的代码步行器即可获得的最接近的宏。
    【解决方案3】:

    单行代码是:

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

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

    【讨论】:

      猜你喜欢
      • 2016-01-13
      • 2011-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-19
      • 2021-07-13
      • 1970-01-01
      • 2011-06-16
      相关资源
      最近更新 更多