I just spent a significant amount of time debugging an issue that boils down to the following:
(defun my-new-alist ()
`((x . nil)))
(setq a (my-new-alist))
(setq b (my-new-alist))
(push 1 (alist-get 'x a))
b ;; ((x . 1))
I expected a
and b
to be independent of each other (that is, I expected my-new-alist
to be pure. Instead, it seems to create a new list when the defun is executed, and always return a reference to that very list. Part of my confusion stems from comparing with the following:
(defun my-new-list ()
nil)
(setq a (my-new-list))
(setq b (my-new-list))
(push 1 a)
a ;; => (1)
b ;; => nil
Note also that anti-quoting the nil part fixes the issue, it seems; that is, the following function doesn't exhibit the problem:
(defun my-new-alist ()
`((x . ,nil)))
What is the significant difference between the list and alist examples? Which parts of the ELisp manual discuss this issue? Why does antiquoting the nil
part fix things?
This question is similar to, but not the same as, Proper reinitialization of a list? What is happening under the hood?. The answers to that question doesn't discuss why using nil
isn't a problem, nor do they explain why antiquoting nil makes a difference. Additionally, I am looking for references in the Emacs lisp manual.
(backquote (form))
behaves the same as(quote (form))
when there are no evaluated or spliced components. Therefore see http://emacs.stackexchange.com/q/20535 and also related Q&As http://stackoverflow.com/q/36964728 (for hash tables) and http://stackoverflow.com/q/18790192 (not elisp specific). – phils Jun 13 '16 at 03:39(eq a b)
before and after thepush
, whereas,nil
creates different objects. IMO the duplicate answer explains that pretty well. – mutbuerger Jun 13 '16 at 03:41(list (list 'x))
, andlist
creates new list structure when invoked. – Drew Jun 13 '16 at 03:55macroexpand
on each of the sexps you are interested in -- e.g.,(push 1 (alist-get 'x a))
– Drew Jun 13 '16 at 04:15