So, I have read from
setq and defvar in lisp,
http://www.cs.ucf.edu/courses/cop4020/spr2006/plsetup.html, and
In Lisp, how do I fix "Warning: Assumed Special?"
among other places about the difference between setf and defvar. So I decided to play around with the idea a bit:
CL-USER> (defun foo ()
(setf x 10)
(print x))
; in: DEFUN FOO
; (SETF X 10)
; ==>
; (SETQ X 10)
;
; caught WARNING:
; undefined variable: X
;
; compilation unit finished
; Undefined variable:
; X
; caught 1 WARNING condition
FOO
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {10040F1543}>.
CL-USER> (foo)
10
10
CL-USER> x
10
Okay, I know that setf should be used to change the value of an existing variable, but the undefined variable warning seems to be handled pretty well in SBCL (though I have read that different CL implementations may handle this differently, thus it isn't the best thing to do).
Enter the second test:
CL-USER> (defun bar ()
(defvar y 15)
(print y))
; in: DEFUN BAR
; (PRINT Y)
;
; caught WARNING:
; undefined variable: Y
;
; compilation unit finished
; Undefined variable:
; Y
; caught 1 WARNING condition
BAR
CL-USER> y
; Evaluation aborted on #<UNBOUND-VARIABLE Y {10045033D3}>.
CL-USER> (bar)
15
15
CL-USER> y
15
As per the links, I changed the setf to defvar which I think should create and bind the variable all at once. Now my undefined variable warning gets pushed into the (print y) line ... what is going on here?
As a secondary question, I am expecting the values of any variables assinged within a funciton to be inaccessible outside of the function, as is the case in Python:
>>> def foo():
... x = 10
... print x
...
>>> foo()
10
>>> x
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
I am guessing this has something to do with the way common lisp deals with scope, ie defvar creates a "global special variabe" ... So I tried one last time with (let ...)
CL-USER> (defun baz () (let ((z 10)) (print z)) (incf z 10) (print z))
; in: DEFUN BAZ
; (INCF Z 10)
; --> LET*
; ==>
; (SETQ Z #:NEW0)
;
; caught WARNING:
; undefined variable: Z
;
; compilation unit finished
; Undefined variable:
; Z
; caught 1 WARNING condition
And after reading What's difference between defvar, defparameter, setf and setq, this one seems to work right:
CL-USER> (defun apple ()
(defparameter x 10)
(print 10))
APPLE
CL-USER> x
; Evaluation aborted on #<UNBOUND-VARIABLE X {1004436993}>.
CL-USER> (apple)
10
10
CL-USER> x
10
Just to reiterate my questions:
1) what is really going on with setf, defvar and let?
2) is there a way to get common lisp to scope the variables inside a function as in the python example?