В Лиспе, как я могу исправить «Предупреждение: Предполагаемый Специальный?» - PullRequest
3 голосов
/ 05 октября 2010

В этом файле я получаю 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 ]

8 голосов
/ 05 октября 2010

Райнер Йосвиг в целом прав.В вашем случае я не вижу необходимости, чтобы эти переменные были глобальными, поэтому лучше всего использовать 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))
7 голосов
/ 05 октября 2010

Любая не определенная переменная может считаться особенной. Другое толкование также не имеет смысла.

Вы можете либо

  • представить ваши переменные как глобальные специальные переменные, используя DEFVAR или DEFPARAMETER

или

  • представить ваши переменные как локальные лексические переменные, используя DEFUN, LAMBDA, FLET, LABELS, LET, LET * или другие

или

  • объявите ваши переменные как специальные или объявите ссылку на переменную как специальную. Обычно это не то, что нужно.

В любом случае, SETQ не определяет или не объявляет переменную. Все, что он делает, это устанавливает существующую переменную в какое-то значение.

Избегайте установки неопределенных / объявленных переменных с помощью SETQ в коде. Его точные последствия не определены в стандарте ANSI Common Lisp.

1 голос
/ 05 октября 2010

Разница в том, что setq, строго говоря, не должен использоваться для определения переменной (я не совсем уверен, почему, поскольку она определяет определение переменной).

Используйте defvar для глобалов и конструкцию let для местных жителей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...