What @phils said in a comment:
"Remember that the value of x is a cons cell."
The cons cell
x is passed to
list, and then it is reversed when
list's second arg is evaluated. Just as you expected.
The result of
list is a list of the cons cell
x (which has been changed) and the result of
Try this, and look at the message:
(let ((x '(1 2 3)))
(message "X: %S" x) (sleep-for 1)
And BTW (for @Tobias, for example), your example has nothing to do with the result of modifying a quoted list being "undefined".
And it's not really undefined, though Common Lisp, which is a spec for any number of implementations, says it is undefined in the spec, because you cannot depend on any particular behavior about it from all implementations. And even Emacs Lisp would not want to tie its implementation hands by specifying any particular behavior for this that the designers would then have to try to maintain (for interpreter, byte-compiler, reader, etc.).
The point about not modifying a "constant" (and it's not a constant), that is, a quoted cons, is this: Do not expect that the sexp
'(some list) gets re-read or re-evaluated each time, if you use it in code that is evaluated more than once. Do not expect that a new list
(some list) gets created each time.
An implementation is free to create a new list (new conses) each time, or some times, or to just reuse the same list that was created during the first read/evaluation.
This is a typical gotcha. Someone writes (let ((x '(1 2 3)))...) in some context, then modifies that list structure, but expects that each time the context is used she gets a new list (new conses) bound to local variable
x. Not necessarily.
The confusion comes from thinking of the program as the program text. The executing program works with things like list structure (conses), that are live. The program can modify some list structure whose apparent representation in the textual program seems to be constant/static.