【问题标题】:macro expansion: to quote the body forms or not?宏扩展:是否引用正文形式?
【发布时间】:2013-06-10 04:48:17
【问题描述】:

我很难准确理解宏扩展的工作原理。 elisp解释器处理这两个sn-ps的代码有什么区别?

(defmacro foo (arg)
  (message "arg is: %s" arg))
(foo "bar")

和:

(defmacro foo (arg)
  `(message "arg is: %s" ,arg))
(foo "bar")

【问题讨论】:

    标签: emacs elisp emacs24


    【解决方案1】:

    您的示例可能令人困惑,因为

    1. message显示一条消息,又返回它。
    2. 字符串(如“bar”)是自求值的。

    指导性示例

    (defconst zzz 123)
    (defmacro zzz1 (arg)
      `(insert (format "arg is: %s" ,arg)))
    (defmacro zzz2 (arg)
      (insert (format "arg is: %s" arg)))
    

    在 3 种形式之后使用 C-x C-e 评估上面的代码。

    现在评估这些:

    第一版:(zzz1 zzz)

    解释器...

    1. 调用zzz1的宏函数
    2. 宏函数返回(insert (format "arg is: %s" zzz))的形式
    3. 解释器评估表单,并将"arg is: 123" 插入当前缓冲区,并返回nil(在底部的回显区域中看到)

    第二版:(zzz2 zzz)

    解释器...

    1. 调用zzz2的宏函数
    2. 宏函数将"arg is: zzz"插入当前缓冲区并返回nil
    3. 解释器将nil 评估为nil(在底部可以看到回声)

    底线

    这里最重要的“要点”是宏只是在(编译器的)解释器启动之前对代码进行操作的函数。

    这些函数的参数未经计算(即在zzz1zzz2 中,argzzz,而不是123)。

    它们像任何其他 lisp 函数一样被评估(例如,它们的主体中可以有宏形式;主体包裹在隐式 progn 中;&c)。

    它们的返回值由解释器评估而不是原始形式。

    【讨论】:

    • 让我失望的是两轮评估。我认为它的行为类似于 C 预处理器——只有一轮评估。我错误的心智模型是宏调用 (zzz2 zzz)(insert (format "arg is: %s" zzz))(宏的主体,但替换了 args)替换,然后进行了评估。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多