#StackBounty: #list #quote When to use quote for lists? Modifying quoted lists in Elisp

Bounty: 200

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).


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.