Here is my answer to the identical question, appropriately edited:
The Bad
foo
is self-modifying code. This is extremely dangerous. While the variable lst
disappears at the end of the let
form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be passed around (just like a number or a list), and, sometimes, modified. This is exactly what you are doing here: the initial value for lst
is a part of the function object and you are modifying it.
Let us actually see what is happening:
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a b c)))) (delq e lst)))
(foo 'c)
==> (a b)
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a b)))) (delq e lst)))
(foo 'b)
==> (a)
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a)))) (delq e lst)))
(foo 'a)
==> nil
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a)))) (delq e lst)))
The Good
In bar
, lst
is initialized to a fresh cons cell and thus is safe.
bar
does not modify its code.
The Bottom Line
In general, it is best to treat quoted data like '(1)
as constants - do not modify them:
quote
returns the argument, without evaluating it. (quote x)
yields x
.
Warning: quote
does not construct its return value, but just returns
the value that was pre-constructed by the Lisp reader (see info node
Printed Representation). This means that (a . b)
is not
identical to (cons 'a 'b)
: the former does not cons. Quoting should
be reserved for constants that will never be modified by side-effects,
unless you like self-modifying code. See the common pitfall in info
node Rearrangement for an example of unexpected results when
a quoted object is modified.
If you need to modify a list, create it with list
or cons
or copy-list
instead of quote
, like you do in bar
.
See more examples.
ps - variable naming
Emacs Lisp is a lisp-2 so these is no reason to name your variable lst
instead of list
.