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

时间:2010-10-05 04:35:03

标签: function lisp warnings 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

整个文件只有两个功能 -

(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)

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

3 个答案:

答案 0 :(得分: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))

编辑:此外,由于您只是在一个地方添加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))

答案 1 :(得分:7)

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

你可以

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

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

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

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

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

答案 2 :(得分:1)

不同之处在于严格来说,setq不应该用于定义变量(我不确定为什么,因为它 定义变量)。

对全局变量使用defvar,为本地人使用let构造。