【发布时间】:2021-11-21 09:05:32
【问题描述】:
假设我有宏 foo 和 bar。如果我写(foo (bar)),我的理解是,在大多数(全部?)lisps 中foo 将被赋予'(bar),而不是bar 如果首先扩展它会扩展。 Some lisps 有类似 local-expand 的东西,foo 的实现可以在继续之前显式请求扩展其参数,但为什么不是默认值?这对我来说似乎更自然。这是历史的偶然,还是有充分的理由像大多数 lisps 那样做?
我一直在 Rust 中注意到我希望宏以这种方式工作。我希望能够在宏调用中包装一堆声明,以便宏可以抓取声明并生成反射信息。但是,如果我使用宏来生成我想要抓取的定义,我包装声明的宏会看到将生成声明而不是实际声明的宏调用。
【问题讨论】:
-
对我来说,首先处理内部形式,然后是父宏,然后是宏引入的所有可能的子项,这看起来更复杂;通常,如果需要,您可以自己在宏中调用 macroexpand,或者像 SBCL 的 code walker 那样更具体的实现函数。我不确定我是否能找到详细讨论这个问题的档案w.r.t。不同的 lisp 版本
-
使用现有方法,宏可以更好地控制其所有子表单,它还可以宏扩展代码本身,例如可以重用符号来表示其他含义,例如 lamda 或 defun,以便以不同方式解释代码(例如静态分析),并且递归宏扩展可以终止
-
@coredump hmm.. 以我描述的方式进行操作的一个动机是它会使宏不那么特别——它们在传递之前评估它们的参数,就像函数一样,只是它们的参数是仅在语法/宏扩展级别“评估”,而不是在运行时表达式级别。它们变得更像运行时函数,恰好采用编译时已知语法,作为优化,我们可以选择在编译时运行它们。但如果这是默认设置,您需要选择退出您描述的案例......
-
@coredump 就像在宏定义中声明一个您不想在传入语法之前扩展的表单列表,因为您打算特别对待它们
标签: macros scheme lisp common-lisp racket