I'm programming on Ubuntu using GCL. From the documentation on Common Lisp from various sources, I understand that let
creates local variables, and setq
sets the values of existing variables. In cases below, I need to create two variables and sum their values.
Using setq
(defun add_using_setq ()
(setq a 3) ; a never existed before , but still I'm able to assign value, what is its scope?
(setq b 4) ; b never existed before, but still I'm able to assign value, what is its scope?
(+ a b))
Using let
(defun add_using_let ( )
(let ((x 3) (y 4)) ; creating variables x and y
(+ x y)))
In both the cases I seem to achieve the same result; what is the difference between using setq
and let
here? Why can't I use setq
(since it is syntactically easy) in all the places where I need to use let
?
Best Answer
setq
assigns a value to a variable, whereaslet
introduces new variables/bindings. E.g., look what happens inThe outer
let
creates a local variablex
, and the innerlet
creates another local variable shadowing the inner one. Notice that usinglet
to shadow the variable doesn't affect the shadowed variable's value; thex
in lined
is thex
introduced by the outerlet
, and its value hasn't changed.setq
only affects the variable that it is called with. This example showssetq
used with local variables, but it can also be with special variables (meaning, dynamically scoped, and usually defined withdefparameter
ordefvar
:Note that
setq
doesn't (portably) create variables, whereaslet
,defvar
,defparameter
, &c. do. The behavior ofsetq
when called with an argument that isn't a variable (yet) isn't defined, and it's up to an implementation to decide what to do. For instance, SBCL complains loudly:Of course, the best ways to get a better understanding of these concepts are to read and write more Lisp code (which comes with time) and to read the entries in the HyperSpec and follow the cross references, especially the glossary entries. E.g., the short descriptions from the HyperSpec for
setq
andlet
include:SETQ
LET
You may want to read more about variables and bindings.
let
andlet*
also have some special behavior with dynamic variables andspecial
declarations (but you probably won't need to know about that for a while), and in certain cases (that you probably won't need to know about for a while) when a variable isn't actually a variable,setq
is actually equivalent tosetf
. The HyperSpec has more details.There are some not-quite duplicate questions on Stack Overflow that may, nonetheless, help in understanding the use of the various variable definition and assignment operators available in Common Lisp:
setq
on undefined variables)