sbcl通用Lisp incf警告

sbcl通用Lisp incf警告,lisp,increment,sbcl,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的正确方法是什

我在学习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的正确方法是什么?

这确实是增加x的方法,或者至少是一种方法。但是,这并不是您要绑定
x
的方式。在CL中,您需要在使用名称之前为其建立绑定,而不仅仅是为其赋值。因此,例如,此代码(在新CL图像中)不是合法CL:

(defun bad ()
  (setf y 2))
通常,这将导致编译时警告和运行时错误,尽管它可能会执行其他操作:其行为未定义

特别是,您所做的事情实际上比这更糟糕:您将一个值插入到
x
符号值中(使用
set
,它会这样做),然后假设像
(incf x)
这样的东西会起作用,这是极不可能做到的。例如,考虑这样的事情:

(defun worse ()
  (let ((x 2))
    (set 'x 4)
    (incf x)
    (values x (symbol-value 'x))))
这是(不同于
糟糕的
)法律代码,但它可能不符合您的要求

许多CL实现确实允许在顶层分配到以前未绑定的变量,因为在对话环境中这很方便。但这些作业的确切含义并不符合语言标准

CMUCL及其衍生产品,包括SBCL,在历史上比当时的其他实现更重视这一点。我认为这是因为解释器比其他大多数解释器更严肃,或者他们秘密地编译了所有的东西,而编译器会把东西捡起来

另一个问题是CL对于顶级变量的语义有点笨拙:如果您使用
defvar
&friends以正常方式建立顶级绑定,那么您也会导致变量是特殊的——动态范围——这是一种普遍的效果:它使该名称的所有绑定都是特殊的。这通常是一个非常不受欢迎的结果。CL作为一种语言,没有顶级词汇变量的概念

因此,许多实现所做的是有某种非正式的概念,即某事物的顶级绑定,这并不意味着一个特殊的声明:如果您只是在顶层说
(setf x 3)
,那么这不会影响整个环境。但随后出现了各种各样的尴尬问题:在这样做之后,
(符号值'x)
的结果是什么

幸运的是,CL是一种功能强大的语言,在该语言中定义顶级词汇变量是完全可能的。这是一个非常粗糙的实现,名为
defflexical
。请注意,还有更好的实现(包括我自己的至少一个,我现在找不到):这不是一个防弹解决方案

(defmacro deflexical (var &optional value)
  ;; Define a cheap-and-nasty global lexical variable.  In this
  ;; implementation, global lexicals are not boundp and the global
  ;; lexical value is not stored in the symbol-value of the symbol.
  ;;
  ;; This implementation is *not* properly thought-through and is
  ;; without question problematic
  `(progn
     (define-symbol-macro ,var (get ',var 'lexical-value))
     (let ((flag (cons nil nil)))
       ;; assign a value only if there is not one already, like DEFVAR
       (when (eq (get ',var 'lexical-value flag) flag)
         (setf (get ',var 'lexical-value) ,value))
       ;; Return the symbol
       ',var)))

看来我需要更多的阅读。你能推荐一个好的信息来源吗?@Hydrocat:我真的不是合适的人选:当我学习CL时,实际上只有CLtL(虽然是一本有趣的书),它并不是一个好的、最新的信息来源。我喜欢保罗·格雷厄姆(Paul Graham)的书,我认为这本书现在是免费的,而说明书也不好学。也许其他人有更好的、更新的想法。哦,很好:)我实际上得到了一本格雷厄姆的书。那我就应该有好帮手了!