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:
quotereturns argument, without evaluating it.(quote x)yieldsx. warning:quotenot 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