首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于普通Lisp编译顺序的问题

关于普通Lisp编译顺序的问题
EN

Stack Overflow用户
提问于 2020-04-21 02:32:51
回答 1查看 184关注 0票数 2

我在一个文件中编写了宏和函数,如下所示:

代码语言:javascript
复制
(defun test ()
  (let ((x '(1 2 3)))
    (macro-test (x real-b)
      (print (+ 1 (car real-b))))))

(defmacro macro-test ((a b) &body body)
  `(do ((,b ,a (cdr ,b)))
       ((not ,b))
     ,@body))

然后在repl中加载这个文件并运行(test)。我发现了一个错误:

代码语言:javascript
复制
The variable REAL-B is unbound.

然而,当我把defmacro 放在 defun之前。百事大吉。

我对常见的lisp编译顺序感到困惑。我知道如果defmacro在内部使用一些函数,那么这些函数应该是(eval-when (:compile-toplevel :load-toplevel :execute)),否则编译将失败。

但是,如果宏定义和函数定义在编译时间是相同的,那么顺序就是问题,对吗?宏应该位于使用它们之前(如果我做了两个函数,顺序就无关紧要了)。我能更详细地了解一下SBCL的编译顺序吗?是只给SBCL的吗?还是普通的Lisp标准?

谢谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-21 05:59:22

顺序总是重要的:当您想要使用宏时,必须知道它。宏执行源转换。如何使用未知的宏进行源转换?

Common标准不需要进行多次编译,首先读取所有源代码,收集所有宏,然后从文件顶部开始编译。在Common中的文件编译只是从头到尾地遍历源代码。以后可能会有多个编译阶段,但这取决于实现.

当宏test未知时,Lisp应该如何编译函数macro-test?Lisp编译器需要( a)知道它是宏,b)它需要有它的定义来展开宏形式。

对于Common,这是一个基本规则:

如果我们有一个表单(foo bar baz),那么计算基本上会查看foo

如果arguments

  • else
  1. 是一个特殊的运算符->,则使用该特殊运算符
  2. ,如果foo是宏运算符->宏,则展开代码并重新启动
  3. ,如果foo是一个函数->调用该函数,则该函数具有求值的foo错误< code >H 217G 218

编译中,它看起来类似于:

如果

  1. 是一个特殊的运算符->,则编译该特殊形式的
  2. 如果foo是宏运算符->宏,则展开宏表单并编译代码
  3. ,如果foo是函数->编译该函数形式H 230H 131else ->警告,然后假设foo是一个函数,然后编译对未来函数的调用H 233G 234
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61335056

复制
相关文章

相似问题

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