编译文件时宏会扩展吗?


13

我有一个宏,需要在使用编译时的每个单个实例中对其进行扩展。有没有一种方法可以这样指定,而无需遍历代码库并仔细包装每个调用eval-when-compile

Answers:


13

字节编译器可访问的所有宏在编译过程中都会扩展。“可达到”实质上意味着不被引用。

defunS,defmacroS,lambdaS,都是字节编译时包含它们的源文件是字节编译。因此,是的,只要它们不在引号(')内,它们内的任何宏都将被扩展。一个非常常见的错误是将lambdas 括在引号中,实际上,这就是为什么您永远不要引用lambdas的原因

这是宏的一大优势,只要编写得当,它们就不会对运行时性能产生影响。当然,另一个优势是它们的功能和多功能性。缺点是您要操纵语法而不是对象,因此存在很多问题的余地,有些是意料之外的,有些是不可避免的。


7

正如Malabarba已经解释的那样,宏在字节编译期间进行了扩展。如果未编译文件,则在加载文件时扩展宏(急切的宏扩展)。

但是不要依赖于此。这是非常糟糕的风格。通常,您不能指望使用您的宏的代码实际上会被编译,并且通常应在编译过程中运行尽可能少的代码。特别是,只有在没有其他方法的情况下,才很少使用宏。根据经验,仅将宏用于语法,而不能将其用于语义(或功能)。

宏是一个泄漏的抽象。它们的扩展在编译时被硬编码到目标代码中,并且不能追溯地更改。随后,目标代码取决于扩展时宏的特定实现。具体来说,它取决于宏主体中使用的所有内部API

因此,在不破坏针对您的宏编译的任何代码的情况下,您无法更改任何此API或宏扩展所依赖的任何内容。

宏对功能的自由使用为依赖地狱铺平了道路


在编写或使用宏时要牢记非常好的要点。
肖恩·艾瑞德

“自由地使用宏来实现功能为依赖地狱铺平了道路。” 直到一个星期前,package.el的一个错误在完全合法的宏依赖情况下完全破坏了软件包的安装。
马拉巴巴

@Malabarba Care提供详细信息?
lunaryorn 2014年

@lunaryorn,你去。讨厌的小问题。
马拉巴巴2014年

1
@lunaryorn我同意宏是危险的(我什至会编辑我的答案以减少对它的称赞:),但是我不认为该错误是它的特定实例。该错误具有其他(几乎没有加剧)的表现,它们根本不涉及宏。它还导致了功能依赖性的问题。
马拉巴巴
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.