emacs - Why does an elisp local variable keep its value in this case? -
could explain me what's going on in simple code snippet?
(defun test-a () (let ((x '(nil))) (setcar x (cons 1 (car x))) x))
upon calling (test-a)
first time, expected result: ((1))
. surprise, calling once more, ((1 1))
, ((1 1 1))
, on. why happening? wrong expect (test-a)
return ((1))
? note after re-evaluating definition of test-a
, return result resets.
also consider function works expect:
(defun test-b () (let ((x '(nil))) (setq x (cons (cons 1 (car x)) (cdr x)))))
(test-b)
returns ((1))
. why aren't test-a
, test-b
equivalent?
the bad
test-a
self-modifying code. extremely dangerous. while variable x
disappears @ end of let
form, initial value persists in function object, , value modifying. remember in lisp a function first class object, can passed around (just number or list), and, sometimes, modified. doing here: initial value x
part of function object , modifying it.
let see happening:
(symbol-function 'test-a) => (lambda nil (let ((x (quote (nil)))) (setcar x (cons 1 (car x))) x)) (test-a) => ((1)) (symbol-function 'test-a) => (lambda nil (let ((x (quote ((1))))) (setcar x (cons 1 (car x))) x)) (test-a) => ((1 1)) (symbol-function 'test-a) => (lambda nil (let ((x (quote ((1 1))))) (setcar x (cons 1 (car x))) x)) (test-a) => ((1 1 1)) (symbol-function 'test-a) => (lambda nil (let ((x (quote ((1 1 1))))) (setcar x (cons 1 (car x))) x))
the good
test-b
returns fresh cons cell , safe. initial value of x
never modified. difference between (setcar x ...)
, (setq x ...)
former modifies object stored in variable x
while latter stores new object in x
. difference similar x.setfield(42)
vs. x = new myobject(42)
in c++
.
the bottom line
in general, best treat quoted data '(1)
constants - not modify them:
quote
returns argument, without evaluating it.(quote x)
yieldsx
. warning:quote
not construct return value, returns value pre-constructed lisp reader (see info node printed representation). means(a . b)
not identical(cons 'a 'b)
: former not cons. quoting should reserved constants never modified side-effects, unless self-modifying code. see common pitfall in info node rearrangement example of unexpected results when quoted object modified.
if need modify list, create list
or cons
or copy-list
instead of quote
.
ps. has been duplicated on emacs.
pps. see why function return different value every time? identical common lisp issue.
Comments
Post a Comment