The Common Lisp Hyper Spec says:
The consequences are undefined if literal objects (including quoted objects) are destructively modified.
This is further motivated at the Constant Modification Issue that lead to the corresponding clarification in the CL Spec.:
CLtL states that an implementation is permitted to "collapse" constants appearing in code to be compiled if they are EQUAL. This implicit sharing of compiled data structures may result in unpredictable behavior if destructive operations are performed. However, CLtL does not explicitly allow or disallow destructive operations on constants.
Does Emacs Lisp have the same behavior/rules as Common Lisp in that aspect?
In the Emacs Lisp Manual there are many examples where quoted lists are assigned to variables and afterwards modified.
Section "Altering the CDR of a List" gives such an example:
> (setq x '(1 2 3))
=> (1 2 3)
(setcdr x '(4))
=> (4)
x
=> (1 4)
On the other hand there is a warning not to use quoted list as non-last element of nconc
in the Emacs manual:
A common pitfall is to use a quoted constant list as a non-last argument to nconc. If you do this, your program will change each time you run it! Here is what happens:
(defun add-foo (x) ; We want this function to add
(nconc '(foo) x)) ; foo to the front of its arg.
(symbol-function 'add-foo)
=> (lambda (x) (nconc (quote (foo)) x))
(setq xx (add-foo '(1 2))) ; It seems to work.
=> (foo 1 2)
(setq xy (add-foo '(3 4))) ; What happened?
=> (foo 1 2 3 4)
(eq xx xy)
=> t
(symbol-function 'add-foo)
=> (lambda (x) (nconc (quote (foo 1 2 3 4) x)))
Is there a complete list of correct rules when to use quoted lists and when not anywhere in the Elisp manual?
Or are those examples in the Emacs manual even erroneous because they modify quoted lists?
Maybe a question of itself: Is there a Spec for Elisp?
An even more simple example for the modification of a function add-foo
through the modification of its return value:
(This is used in the discussion with Drew in the comments.)
(defun add-foo ()
'(1 2 3))
(setq x (add-foo))
(setq x (nconc x 4))
(add-foo)
The last statement gives (1 2 3 . 4)
.
add-foo
and the list returned to the user are the same. Changing one changes the other (because they are actually the same). That is not the point of the question. The actual point is: What are the basic assumptions about Elisp lists where the programmer can count on? The manual gives the impression that for Emacs lists there are more restrictive assumptions than for CL implying that they give the programmer more freedom to use them. But on the other hand the manual alarms one that quoted lists are not like generated lists. AFAIK there is no clear Spec.cons
andlist
create new list structure. Nothing more. If you think the manual gives another impression then maybe file a bug about that, maybe suggesting it's not clear. The text you cite doesn't seem problematic to me. You can certainly assign a quoted list to a variable and then modify that list. All that you need to be aware of is that you are assigning a cons and modifying that cons. The warning aboutnconc
is just a reminder to be aware of code that modifies list structure. Changing list structure requires vigilance.