Subject: bug#40671: [DOC] modify literal objects

From: Michael Heerdegen <[email-masked]>
Date: Mon, 20 Apr 2020 02:53:35 +0200

Paul Eggert <[email-masked]> writes:

> > (let ((l (list 1 2 3)))
> >    `',l)
> > ==> '(1 2 3)
> > If you evaluate this (the return value is a valid expression),
> > `quote'
> > returns a list, but it's not a list literal.
>
> Sure, but one shouldn't be modifying that list. Once you hand a Lisp
> object to 'eval', modifying that object later ought to be a no-no even
> if the interpreter happens to do something non-crashy now.

But I can modify the list before handing it over to `eval',
e.g. replacing the `1' with `cons'.

And even when I eval the original list, I get just the same l as before:

 (let ((l (list 1 2 3)))
    `',l
    (eq l (eval `',l)))

==> t.

AFAIU the problematic entities are the literal lists created by the
reader and the compiler.

> >>> (let ((l (list 1 2 3)))
> >>>     (let ((my-vector `[,@l]))
> >>>       my-vector))

> OK, how about if we append the following sentence to that section:
>
>   As an exception to the above rules, a vector within a backquote construct
> is not considered to be a constant if it contains a substitution or splice.

> That is, the backquote causes the vector to (a) not be considered a
> constant, (b) be newly created each time the backquote is evaluated,
> and (c) mutable. The (a) and (b) parts fix problems that were already
> there in the longstanding documentation; the (c) part is new.

Here your perspective becomes complicated.

The Lisp reader reads the vector [,@l] while reading the program.  That
vector is never used by the program, because already the expansion of
the code does not include a vector any more:

(macroexpand-all
 '(let ((l (list 1 2 3)))
    (let ((my-vector `[,@l]))
      my-vector)))

==>

(let
    ((l (list 1 2 3)))
  (let ((my-vector
         (vconcat l)))
    my-vector))

Only symbols, numbers, and lists.

Any other macro could do something similar, so backquote is not just an
exception, and was only an example that came to my mind first.  If the
definition of backquote would try to modify the read [,@l] vector, this
vector of length 1, we would have a problem.  But it only analyses this
vector to produce some other code that doesn't even contain a vector any
more.

We must distinguish between the objects created when a program is
read/compiled, i.e. the objects a program consists of (data and programs
are the same in Lisp, etc.), and the objects that that program actually
handles when it runs.

Michael.