gpt4 book ai didi

compilation - 关于Common Lisp编译顺序的问题

转载 作者:行者123 更新时间:2023-12-04 02:52:51 25 4
gpt4 key购买 nike

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

(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)。我收到此错误:

The variable REAL-B is unbound.

但是,当我将 defmacro 放在 defun 之前时。一切都很好。

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

但是,如果宏定义和函数定义在编译时相同,那么顺序很重要,对吧?宏应该位于使用它们的位置之前(如果我创建两个函数,顺序无关紧要)。我可以详细了解 SBCL 的编译命令吗?它只适用于 SBCL 吗?还是 Common Lisp 的标准?

谢谢!

最佳答案

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

Common Lisp 标准不需要多次编译,即首先读取所有源代码并收集所有宏,然后从文件顶部开始编译。 Common Lisp 中的文件编译只是从头到尾遍历源代码。稍后可能会有多个编译阶段,但这留给了实现......

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

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

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

  1. 如果 foo 是一个特殊的运算符 -> 使用那个特殊的运算符
  2. 如果 foo 是宏运算符 -> 宏展开代码并重新开始
  3. 如果 foo 是一个函数 -> 使用评估的参数调用该函数
  4. else -> 一个错误

编译中看起来很相似:

  1. 如果 foo 是一个特殊的运算符 -> 编译那个特殊的形式
  2. 如果 foo 是一个宏运算符 -> macro 展开宏形式并编译该代码
  3. 如果 foo 是一个函数 -> 编译那个函数形式
  4. else -> 发出警告,然后假设 foo 是一个函数,并编译调用该名称的 future 函数

关于compilation - 关于Common Lisp编译顺序的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61335056/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com