Reputation: 95
Just started learning lisp. I have no idea why I am getting these errors or even what they mean. I am simply trying to code an approximation of pi using the Gregory-Leibniz series, here is the code.
(defun gl (n)
(defparameter x 0) ;init variable to hold our runnning sum
(loop for y from 0 to n ;number of iterations, starting from 0 to desired n
(if (= y 0) ;if n is 0 then we just want 4
(defparameter w 4))
(if (> y 0) ;else, 4*(-1^y)/((2 * y)+1)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w)) ;add to our running sum
(write x)) ;once loop is over, print x.
I have tried using setq, defvar, let etc. instead of defparameter but I still get "Undeclared free variable X".
I also get the error "Unused lexical variable N" even though I am using it for my loop, which is weird also.
How can I fix this and why is it happening? Thanks!
Upvotes: 3
Views: 816
Reputation: 38967
Here is the code after Emacs auto-indented it:
(defun gl (n)
(defparameter x 0)
(loop for y from 0 to n
(if (= y 0)
(defparameter w 4))
(if (> y 0)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w))
(write x))
Compiling the following code with SBCL gives one error and two warnings.
One warning says that x
is undefined.
You should not call defparameter
from inside your function, since defvar
and defparameter
are used to declare dynamic variables and to set their value in the global scope. Prefer to have let bindings, or, since you already are using a loop, a with
clause. When you want to modify a binding, use setf
.
The errors comes from the macroexpansion of LOOP
, which is malformed. For SBCL, that means that the code is treated as dead-code for the rest of the function compilation; that explains why n
appears not to be used, which is what the second warning is about.
There are various fixes remaining to be done:
EXPT
, not EXP
.(+ x w)
only computes a value but does not modify x
, the result is useless.if
as expression, like a ternary operator in other languages, in your case the code can be simplified1+
(that's the name of the function, not a special syntax for adding constants)write
operation is rarely needed, especially if you are computing a mathematical formula; just return the value, and the REPL will print it automatically.Small corrections that make your code works:
(defun gl (n)
(let ((x 0))
(loop
for y from 0 to n
for w = (if (= y 0)
4
(* 4 (/ (expt -1 y) (+ (* 2 y) 1))))
do (setf x (+ x w)))
(write x)))
I would personally get rid of x
and w
, and use a SUM
loop clause.
(defun gl (n)
(loop
for y from 0 to n
sum (if (zerop y)
4
(* 4 (/ (expt -1 y)
(1+ (* 2 y)))))))
Upvotes: 6