在Lisp中,如何修复"警告:假设特殊?"

Ste*_*ing 3 lisp warnings function common-lisp

在这个文件中,我得到9个"假定特殊"的警告.他们是

;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special in SETQ
;;;*** Warning in CHECK-ROW: RESULT assumed special in SETQ
;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special
;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special
;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special
;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special
;;;*** Warning in CHECK-ROW: CHECKARRAY assumed special
;;;*** Warning in CHECK-ROW: RESULT assumed special in SETQ
;;;*** Warning in CHECK-ROW: RESULT assumed special
Run Code Online (Sandbox Code Playgroud)

整个文件只有两个功能 -

(defun get-element (x y board)
 (nth y (nth x board)))

(defun check-row (row board)
 (setq checkarray (make-array 9))
 (setq result T)
 (fill checkarray 0)
 (loop for i upto 8 do
  (setf (aref checkarray (- (get-element row i board) 1))
        (+  (aref checkarray (- (get-element row i board) 1)) 1))
 )
 (loop for i upto 8 do
  (if (or (= (aref checkarray i) 0) (> (aref checkarray i) 1))
      (setq result nil) ())
 )
 result)
Run Code Online (Sandbox Code Playgroud)

我没有得到任何错误,功能似乎工作正常.那为什么这么说呢?我该如何解决?

zem*_*zem 8

Rainer Joswig的回答一般是正确的.在你的情况下,我认为没有必要将这些变量设置为全局变量,所以最好的办法是let使它们在函数体上是局部变量:

(defun check-row (row board)
  (let ((checkarray (make-array 9)) (result t))
    (fill checkarray 0)
    (loop for i upto 8 do
         (setf (aref checkarray (- (get-element row i board) 1))
               (+  (aref checkarray (- (get-element row i board) 1)) 1)))
    (loop for i upto 8 do
         (if (or (= (aref checkarray i) 0) (> (aref checkarray i) 1))
             (setq result nil) ()))
    result))
Run Code Online (Sandbox Code Playgroud)

编辑:此外,由于您只是在一个地方添加1,您可以使用incf而不是那个长setf:

(defun check-row (row board)
  (let ((checkarray (make-array 9)) (result t))
    (fill checkarray 0)
    (loop for i upto 8 do
         (incf (aref checkarray (- (get-element row i board) 1))))
    (loop for i upto 8 do
         (if (or (= (aref checkarray i) 0) (> (aref checkarray i) 1))
             (setq result nil) ()))
    result))
Run Code Online (Sandbox Code Playgroud)


Rai*_*wig 7

任何未定义的变量都可以被认为是特殊的.另一种解释也没有多大意义.

你可以

  • 使用DEFVAR或DEFPARAMETER将变量引入全局特殊变量

要么

  • 使用DEFUN,LAMBDA,FLET,LABELS,LET,LET*等将您的变量引入本地词汇变量

要么

  • 将变量声明为特殊变量或将变量引用声明为特殊变量.通常这不是人们想要的.

无论如何,SETQ没有定义或声明变量.它所做的就是将现有变量设置为某个值.

避免在代码中使用SETQ设置未定义/声明的变量.其确切后果在ANSI Common Lisp标准中未定义.