sbcl Common Lisp incf警告

时间:2016-10-18 03:06:01

标签: lisp increment sbcl

我正在关注lisp的教程,他们做了以下代码

(set 'x 11)
(incf x 10)

和解释器给出了以下错误:

; in: INCF X
;     (SETQ X #:NEW671)
; 
; caught WARNING:
;   undefined variable: X
; 
; compilation unit finished
;   Undefined variable:
;     X
;   caught 1 WARNING condition

21

增加x的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

这确实是你要增加x的方式,或至少有一种方法。但是,你不应该如何绑定x。在CL中,您需要在使用之前为名称建立绑定,而不是仅通过分配它来实现。因此,例如,此代码(在新的CL映像中)不合法CL:

(defun bad ()
  (setf y 2))

通常这会导致编译时警告和运行时错误,尽管它可能会执行其他操作:未定义其行为。

你所做的事情,特别是,实际上比这更糟糕:你已经将一个值夯入了symbol-value的{​​{1}}(x,这样做了),然后假设像set这样的东西会起作用,这是不可能的。例如,考虑这样的事情:

(incf x)

这是(与(defun worse () (let ((x 2)) (set 'x 4) (incf x) (values x (symbol-value 'x)))) )合法代码不同,但它可能无法按照您的意愿执行。

许多CL实现允许在顶层分配以前未绑定的变量,因为在会话环境中它很方便。但这种作业的确切含义超出了语言标准。

CMUCL及其衍生产品,包括SBCL,在历史上比其他实施当时更加认真。我认为这样做的原因是解释器比其他大多数人更严重和/或他们秘密编译了所有内容并且编译器选择了。

另一个问题是CL对于顶级变量有一些稍微笨拙的语义:如果你努力以正常的方式建立一个顶层绑定,bad&朋友们,那么你也会使变量成为特殊的 - 动态作用域 - 这是一种普遍的效果:它使该名称的所有绑定变得特别。这通常是一个非常不理想的后果。 CL作为一种语言,没有顶级词汇变量的概念。

因此,有许多实现方式是对某些东西的顶级绑定采取某种非正式概念,这并不意味着特殊声明:如果你只是在顶层说defvar那么这就不会控制整个环境。但后来有各种各样的尴尬问题:在这之后,例如(setf x 3)的结果是什么?

幸运的是,CL是一种功能强大的语言,很有可能定义语言中的顶级词汇变量。这是一个名为(symbol-value 'x)的非常hacky实现。请注意,那里有更好的实现(包括我至少有一个,我现在找不到):这并不是一个防弹解决方案。

deflexical