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 Spe
answering 2) DEFVAR defines a variable. But it has not been executed. So the compiler does not know about the variable in the print form - when compiling the DEFUN form.. It's also inside a DEFUN. Thus it is not on the top-level. As a top-level form the compiler would recognize the DEFVAR and would notice that y is a global special variable.
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?
1) SETF sets a variable value, but does not define it. If that variable is undefined, then the Common Lisp standard does not really say what happens. Most Common Lisp implementations will do something useful. Typically it gets executed as if the variable would have been declared special (thus you also get a warning).
DEFVAR is used as a top-level form (usually not inside functions) to define global special variables. Since DEFVAR declares the variable name to be special, it is a very useful convention to write a variable with stars around it: *y* instead of just y.
LET defines a scope for local variables.
2) Common Lisp functions have the parameter list to introduce variables. Other than that they don't define a variable scope. If you want to introduce a local variable inside a function, use LET.
>>> def foo():
... x = 10
... print x
Is
(defun foo ()
(let ((x 10))
(print x)))
Again: a function does not provide a scope for variables, such that assigning a variable inside a function will automagically define it to be function-local. Use LET instead.
Note also that LET is syntactic sugar, mostly: (let ((a 1) (b 2)) (+ a b)) is basically doing the same as ((lambda (a b) (+ a b)) 1 2). It's just a simple function application written differently to improve it for the human reader.
There is also support in Common Lisp for an older syntax:
(defun foo (&aux (x 10))
(print x))
Above defines a local variable X, just like a LET would do.
I'll keep it short and simple:
1) what is really going on with setf, defvar and let?
defvar and defparameter are used to declare and set globally special variables. They only differ when the name is already bound.
setf is used for assignment (to special variables, lexical variables, and other – possibly custom – setfable places.)
let (and let*) creates new variable bindings that are visible inside its body. It may create either lexical or special bindings, depending on (global or local) declarations. If there are no special declarations, lexical bindings will be created.
2) is there a way to get common lisp to scope the variables inside a function as in the python example?
Put the code inside let's body, where the binding is visible:
CL-USER> (defun baz ()
(let ((z 10))
(print z)
(incf z 10) ; i.e. (setf z (+ z 10))
(print z)))
BAZ
CL-USER> (baz)
10
20
20
CL-USER> z
; Evaluation aborted on #<UNBOUND-VARIABLE #x186C611E>.