Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lisp warning: xx is neither declared nor bound, it will be treated as if it were declared SPECIAL

I am new to lisp and am writing a few simple programs to get more familiar with it. One of the things I am doing is writing a recursive and iterative version of a factorial method. However, I have come across a problem and can't seem to solve it.

I saw a similar error at Lisp: CHAR is neither declared nor bound but a solution wasn't actually reached, other than the OP realized he made a "typing mistake". In the REPL I can use the setf function and it works fine. I am also using LispBox with emacs. I would appreciate any suggestions!

(defun it-fact(num)
  (setf result 1)
  (dotimes (i num)
    (setf result (* result (+ i 1)))
  )
)

WARNING in IT-FACT : RESULT is neither declared nor bound, it will be treated as if it were declared SPECIAL.

like image 530
Aaron Avatar asked Sep 06 '09 08:09

Aaron


3 Answers

There are a few things wrong or not so good Lisp style:

(defun it-fact(num)                      ; style: use a space before (
  (setf result 1)                        ; bad: variable RESULT is not introduced
  (dotimes (i num)
    (setf result (* result (+ i 1)))     ; bad: extra addition in each iteration
  )                                      ; style: parentheses on a single line
)                                        ; bad: no useful return value

A possible version:

(defun it-fact (num)
  (let ((result 1))                      ; local variable introduced with LET
    (loop for i from 1 upto num          ; I starts with 1, no extra addition
      do (setf result (* result i)))
    result))                             ; result gets returned from the LET
like image 168
Rainer Joswig Avatar answered Nov 20 '22 05:11

Rainer Joswig


In Lisp, local variables must be explicitly declared with LET or other forms that create local variables. That differs from e.g. Python or JavaScript where assignment to variable creates the variable in current lexical scope.

Your example can be rewritten like this:

(defun it-fact(num)
  (let ((result 1))
    (dotimes (i num)
      (setf result (* result (+ i 1))))))

An off-topic comment: there is no point in putting closing parentheses on separate lines.

like image 24
dmitry_vk Avatar answered Nov 20 '22 05:11

dmitry_vk


You need to bind the variable 'result' - using 'let', for example - before starting to use it:

(defun it-fact(num)
  (let ((result 1))
    (dotimes (i num)
      (setf result (* result (+ i 1))))))

For futher details you might want to read this ...

like image 5
Johan Kullbom Avatar answered Nov 20 '22 05:11

Johan Kullbom