首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在代码编译/计算期间展开嵌套宏调用

在代码编译/计算期间展开嵌套宏调用
EN

Stack Overflow用户
提问于 2018-11-16 13:13:17
回答 1查看 141关注 0票数 0

我有下一段代码:

代码语言:javascript
复制
(in-package :cl-user)

(defmacro test0 (form)
  (format t "test0: Expander phase: ~s" form)
  `(format t "test0: Expansion phase: ~s" ,form))

(defmacro test1 (form)
  (format t "test1: Expander phase: ~s" form)
  (test0 form)
  `(format t "test1: Expansion phase: ~s" ,form))

常见的Lisp实现:"SBCL 1.3.16"

  1. (compile-file "source.lisp"); compiling (IN-PACKAGE :CL-USER) ; compiling (DEFMACRO TEST0 ...) ; compiling (DEFMACRO TEST1 ...)test0: Expander phase: FORMtest0: Expander phase: FORM结果
  2. (load "source.lisp"); #<PACKAGE "COMMON-LISP-USER"> ; TEST0 test0: Expander phase: FORM ; TEST1结果

我只是无法理解接下来的事情:

  1. 为什么嵌套子表单(test0 form)test1宏的定义中被扩展和处理?为什么它不在宏调用中处理呢?
  2. 公共Lisp标准在哪里指定这样的行为?eval-when?文件编译?表格评估?
  3. 最后,为什么"test0: Expander phase: FORM"在编译期间(compile-file)只打印两次,在计算期间(load)只打印一次?

我认为答案很明显,但我找不到。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-16 14:31:12

宏是对代码进行操作的函数。因为在Lisp中,代码只是一个list,所以宏函数看起来像普通的函数。

您的defmacro test1被看作是函数的定义,所以当SBCL编译defmacro test1时,所有的代码都会被适当地处理,并且(test0 form)会被宏扩展。这回答了q1。

load“依次执行它遇到的每个表单”,因此要回答您的q2,您需要读取3.1评价,特别是3.1.2.1.2.2宏观形式

至于一个宏展开了多少次,这不是由标准指定的(实现可以在用户函数的每个调用中扩展它!),这也是为什么宏产生副作用(例如,进行输出)不是一个好主意的原因。在您的情况下,当定义test1时,加载需要扩展。编译在定义test1时扩展,然后在编译时再次扩展。记住,defmacro安排宏可以在下面的代码中使用(包括递归地使用),因此必须立即定义。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53338637

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档