为什么setf在repl中工作但在编译时出错?

时间:2014-01-01 16:13:10

标签: common-lisp clisp

当我在repl中使用setf它工作正常,但如果我尝试在文件中使用它然后编译并将其发送到repl,则会出错。为什么我会看到这种奇怪的行为?

在repl中正常工作:

(setf books 
  '((war-and-peace leo-tolstoy)
(spin charles-wilson)
(harry-potter jk-rowling)
(speaker-for-the-dead orson-scott-card)))

从文件编译时出现此错误:

clagitsc.lisp:187:1:
warning: 
BOOKS is neither declared nor bound,
it will be treated as if it were declared SPECIAL.
warning: 
in #:|187 193 (SETF BOOKS '(# # # ...))-34| in lines 187..193 : BOOKS is neither    
declared nor bound,
it will be treated as if it were declared SPECIAL.

Compilation failed.

我正在使用带有CLisp 2.49的Windows上的emacs 24.3,我正在通过Common Lisp:一个温和的符号计算简介。

2 个答案:

答案 0 :(得分:2)

这是因为书籍没有明确地声明为变量。在repl模式下,你的lisp可能默默地认为它是特殊的,但在编译期间它会抛出一个警告。您可以使用defvar或defparameter表单“创建”全局动态变量。 (在此处阅读更多内容:http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/mac_defparametercm_defvar.html)。 要创建类似C的全局变量(只是全局变量,即在所有线程之间共享值),您应该在CLisp中找到sb-ext:defglobal的模拟。

答案 1 :(得分:2)

在Common Lisp中未定义设置未声明变量的确切效果。在CLISP中,您会收到警告。但是警告不是错误,因此在CLISP中编译通常不会失败。

现在我们把它写成

(defvar *books* '(...))

并使用变量*books*清楚地表明它是一个全局声明为特殊的变量。它可以防止冲突与词汇变量。