【问题标题】:Are Lisp macros just syntactic sugar?Lisp 宏只是语法糖吗?
【发布时间】:2022-11-29 18:27:33
【问题描述】:

我一直在读到 Lisp 宏是该语言最强大的特性之一。但是阅读规范和手册,它们只是参数未评估的函数。

给定任何宏(defmacro example (arg1 ... argN) (body-forms)),我可以只写(defun example (arg1 ... argN) ... (body-forms)),最后一个主体形式变成一个列表,然后像(eval (example 'arg1 ... 'argN)) 一样调用它来模拟宏的相同行为。如果是这样的话,那么宏就只是语法糖,但我怀疑语法糖是否会被称为强大的语言功能。我错过了什么?是否存在我无法执行此过程来模拟宏的情况?

【问题讨论】:

    标签: macros lisp


    【解决方案1】:

    我不能谈论强大的因为它可能有点主观,但宏是处理 Lisp 数据的常规 Lisp 函数,所以它们就像富有表现力的作为其他功能。其他语言中的模板或通用函数不是这种情况,它们更多地依赖静态类型并且(有意)受到更多限制。

    在某种程度上,是的,宏是简单的句法工具,但您的仿真重点是宏的动态语义,即。如何运行在运行时计算宏的代码。然而:

    • 使用eval的代码不等同于扩展代码
    • 宏的预处理/编译时方面未被模拟

    词法范围

    函数,如+,不继承词法作用域:

    (let ((x 30))
      (+ 3 4))
    

    在+ 的定义中,您无法访问x。能够做到这一点就是“动态范围”的意义所在(更准确地说,请参见动态范围,无限范围变量)。但是现在依赖动态作用域是个例外。大多数函数使用词法作用域,eval 也是如此。

    eval 函数计算无效的词法环境,它永远无法访问周围的词法绑定。因此,它的行为类似于任何常规函数。

    因此,在您的示例中,在转换后的源代码上调用 eval 将不起作用,因为 arg1 到 argnN 可能未绑定(这取决于您的宏的作用)。

    为了具有等效的形式,您必须在转换后的代码中注入绑定,或者在更高级别进行扩展:

    (defun expand-square (var)
      (list '* var var))
    
    ;; instead of:
    (defun foo (x) (eval (expand-square 'x))) ;; x unbound during eval
    
    ;; inject bindings
    (defun foo (x) (eval `(let ((z ,x)) (expand-square z))))
    
    ;; or expand the top-level form
    (eval `(defun foo (x) ,(expand-square 'x)))
    

    请注意,宏也可以通过其 lambda 列表中的 &environment 参数访问词法环境。此环境的使用依赖于实现,但可用于访问与变量关联的声明,例如。

    还要注意在最后一个例子中你是如何评估代码的定义函数,而不是什么时候跑步它。这是关于宏的第二件事。

    扩张时间

    为了模拟宏,您可以通过在运行时模拟它的形式在本地替换对宏的调用(使用 let 捕获您希望在扩展代码中看到的所有绑定,这很乏味),但是您会错过了宏的有用方面,即:提前生成代码。

    上面的最后一个示例显示了如何引用 defun 并将其包装在 eval 中,如果您想模拟宏完成的预处理工作,基本上您需要对所有函数都这样做。

    宏系统是一种以易于使用的方式将此预处理步骤集成到语言中的方法。

    结论

    当函数不能时,宏本身是抽象事物的好方法。例如,您可以使用更人性化、更稳定的语法来隐藏实现细节。这就是您在 Common Lisp 中定义模式匹配能力的方式,使它们看起来像是语言的一部分,而没有太多的运行时惩罚或冗长。

    它们依赖于语言中集成的简单术语重写函数,但您可以根据需要在编译时或运行时自己模拟它们的行为。它们可用于执行不同类型的抽象,这些抽象通常在其他语言中缺失或更麻烦,但也有局限性:它们自己不“理解”代码,它们不提供访问所有功能的权限编译器(类型传播等),但它们是可移植的。

    【讨论】:

      猜你喜欢
      • 2015-09-04
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      • 2011-03-08
      • 2019-06-09
      • 2013-11-28
      • 2014-09-18
      • 2016-07-25
      相关资源
      最近更新 更多