A local variable is a variable which has a temporary value while a program is executing, for example, when a function is called the variables which are the names of its arguments are temporarily bound (a binding is a particular instance of a local variable) to the values of the arguments passed to the function. When the function call exits its arguments are unbound and the previous definitions of the variables come back into view.
Even if a variable has more than one binding still `active' only the most recent is visible -- there is absolutely no way the previous bindings can be accessed until the bindings are unbound one-by-one.
A nice way of visualising variable binding is to think of each variable as a stack. When the variable is bound to, a new value is pushed onto the stack, when it is unbound the top of the stack is popped. Similarly when the stack is empty the value of the variable is void (see section Void Variables). Assigning a value to the variable (see section Setting Variables) overwrites the top value on the stack with a new value. When the value of the variable is required it is simply read from the top of the stack.
Apart from function calls there are two special forms which perform
variable binding (i.e. creating local variables), let and let*.
let creates new variable bindings as specified by the bindings
argument then evaluates the body-forms in order. The variables
are then unbound to their state before this let form and the
value of the implicit progn of the body-forms becomes the value
of the let form.
The bindings argument is a list of the bindings to perform. Each binding is either a symbol, in which case that variable is bound to nil, or a list whose car is a symbol. The cdr of this list is a list of forms which, when evaluated, give the value to bind the variable to.
(setq foo 42)
=> 42
(let
((foo (+ 1 2))
bar)
;; Body forms
(setq foo (1+ foo)) ;This sets the new binding
(cons foo bar))
=> (4 . nil)
foo
=> 42 ;The original values is back
Note that no variables are bound until all the new values have been
computed (unlike in let*). For example,
(setq foo 42)
=> 42
(let
((foo 100)
(bar foo))
(cons foo bar))
=> (100 . 42)
Although foo is given a new binding this is not actually done
until all the new bindings have been computed, hence bar is bound to
the old value of foo.
let except for one
important difference: the new bindings are installed as they are
computed.
You can see the difference by comparing the following example with the
last example in the let documentation (above),
(setq foo 42)
=> 42
(let* ;Using let* this time
((foo 100)
(bar foo))
(cons foo bar))
=> (100 . 100)
By the time the binding of bar is computed the new binding of
foo has already been installed.
Go to the first, previous, next, last section, table of contents.