语句不按顺序执行? (let 语句中的 defvar)
我试图将其减少到最小的示例。代码运行没有错误,产生预期的输出。但它警告我,我的第一个变量未定义。看来 progn 的第二个语句没有“看到”第一个语句的结果。感谢您的帮助!
(我最初在代码中根本没有 progn 构造,但是在收到此错误后,我添加了它以查看是否会强制按顺序执行 - 但错误是相同的。)
这是代码:
(let ((input (open "input.lisp")))
(progn (defvar var1 (read input))
(defvar arr1 (make-array var1 :initial-contents (read input))))
(close input))
(print var1)
(print arr1)
这些是内容文件“input.lisp”的:
9
(10 8 6 4 2 4 6 8 10)
这是执行后我从 sbcl 获得的输出(加载“test.lisp”):
; in: DEFVAR ARR1
; (MAKE-ARRAY VAR1 :INITIAL-CONTENTS (READ INPUT))
;
; caught WARNING:
; undefined variable: VAR1
;
; compilation unit finished
; Undefined variable:
; VAR1
; caught 1 WARNING condition
9
#(10 8 6 4 2 4 6 8 10)
T
所以,在我看来,两个定义语句都在执行,但第二个定义语句没有“看到” “第一的结果。它仍然正确地构造数组,因为它填充了给定的初始内容。但为什么 var1 还没有定义呢?
I've tried to reduce it to the minimal example. The code runs without an error, producing the expected output. But it gives me a warning that my first variable is undefined. It seems that the second statement of progn doesn't "see" the results of the first statement. Thanks for the help!
(I originally did not have the progn construct in the code at all, but after getting this error I added it to see if that would force execution in order -- but the error is the same.)
Here's the code:
(let ((input (open "input.lisp")))
(progn (defvar var1 (read input))
(defvar arr1 (make-array var1 :initial-contents (read input))))
(close input))
(print var1)
(print arr1)
These are the contents of the file "input.lisp":
9
(10 8 6 4 2 4 6 8 10)
And this is the output I get from sbcl after executing (load "test.lisp"):
; in: DEFVAR ARR1
; (MAKE-ARRAY VAR1 :INITIAL-CONTENTS (READ INPUT))
;
; caught WARNING:
; undefined variable: VAR1
;
; compilation unit finished
; Undefined variable:
; VAR1
; caught 1 WARNING condition
9
#(10 8 6 4 2 4 6 8 10)
T
So, it seems to me that both definition statements are executing, but the second doesn't "see" the results of the first. It still constructs the array correctly because it's filled with the given initial-contents. But why isn't var1 already defined?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
请参阅 Hyperspec 中的 defvar 文档 :
这意味着(SBCL 似乎就是这种情况)如果
defvar
作为非顶级形式出现,则编译器不需要识别该名称已被声明。那么为什么你的 defvar 没有被编译为顶级形式呢?请参阅第 3.2.3.1 节,顶级表单的处理(第 6 点)答案是:代码周围的let
会导致它被编译为非顶级形式。因此,您需要在顶层
defvar
变量,然后稍后在let
中使用setf
分配它们。像这样。使用
with-open-file
< 通常也更简单/a> 而不是打开
和关闭
。您遇到此问题的原因是您将代码放置在文件的顶层。这是一件有点不寻常的事情:正常的 Lisp 编码风格是将大部分代码放在函数定义中,然后在需要运行它们时调用这些函数。
例如,这将是编写此类代码的更典型方法,初始化代码位于其自己的函数中。
See the documentation for
defvar
in the Hyperspec:This implies (and it seems to be the case for SBCL) that if a
defvar
appears as a non-top-level form, then the compiler need not recognize that the name has been declared. So how come yourdefvar
s are not being compiled as top level forms? See section 3.2.3.1, Processing of Top Level Forms (point 6) for the answer: thelet
surrounding your code causes it to be compiled as non-top-level forms.So you need to
defvar
your variables at top level, and then assign them later on withsetf
inside thelet
.Like this. It's also usually simpler to use
with-open-file
rather thanopen
andclose
.The reason that you are having this trouble is that you are placing your code at top level in the file. This is a slightly unusual thing to do: the normal Lisp coding style is to put most of your code in function definitions, and then to call those functions when you need to run them.
For example, this would be a more typical way to write this kind of code, with the initialization code in its own function.