Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Lisp, how do I fix "Warning: Assumed Special?"

In this file I get 9 warnings of "assumed special". They are

;;;*** 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

The whole file is just two functions -

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

I don't get any errors and the functions seem to work fine. So why does it say this? And how can I fix it?

like image 310
Sterling Avatar asked Dec 03 '22 11:12

Sterling


2 Answers

Any variable not defined may be assumed to be special. Another interpretation also does not really make sense.

You may either

  • introduce your variables as global special variables using DEFVAR or DEFPARAMETER

or

  • introduce your variables as local lexical variables using DEFUN, LAMBDA, FLET, LABELS, LET, LET* or others

or

  • declare your variables as special or declare the variable reference as special. Usually this is not what one wants.

Anyway, SETQ does not define a or declare a variable. All it does is that it sets an existing variable to some value.

Avoid setting undefined/declared variables with SETQ in code. Its exact consequences are undefined in the ANSI Common Lisp standard.

like image 78
Rainer Joswig Avatar answered Jan 14 '23 17:01

Rainer Joswig


Rainer Joswig's answer is correct in general. In your case, I don't see any need for these variables to be global, so the best thing to do is use let to make them local to the body of your function:

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

Edit: Also, since you're just adding 1 to a place, you can use incf instead of that long 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))
like image 30
zem Avatar answered Jan 14 '23 17:01

zem