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

后端 未结 3 1772
囚心锁ツ
囚心锁ツ 2020-12-18 12:24

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: R         


        
相关标签:
3条回答
  • 2020-12-18 13:04

    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.

    0 讨论(0)
  • 2020-12-18 13:09

    The difference is that setq is not, strictly speaking, supposed to be used to define a variable (I am not exactly sure why, since it does define a variable).

    Use defvar for globals and the let construct for locals.

    0 讨论(0)
  • 2020-12-18 13:19

    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))
    
    0 讨论(0)
提交回复
热议问题