Замечание о том, что ваша ментальная модель цитирования может быть ошибочной, является превосходным - хотя оно может или не может применяться в зависимости от того, что это за ментальная модель.
Во-первых, помните, что существуют различные этапы выполнения программы. Среда Lisp должна сначала прочитать текст программы в структуры данных (списки, символы и различные литеральные данные, такие как строки и числа). Затем он может или не может скомпилировать эти структуры данных в машинный код или в некоторый промежуточный формат. Наконец, полученный код оценивается как (конечно, в случае машинного кода это может означать просто переход на соответствующий адрес).
Давайте пока отложим проблему компиляции и сосредоточимся на этапах чтения и оценки, предполагая (для простоты), что входные данные оценщика - это список структур данных, читаемых читателем.
Рассмотрим форму (QUOTE x)
, где x - это некоторое текстовое представление объекта. Это может быть символьный литерал, как в (QUOTE ABC)
, список литералов, как в (QUOTE (A B C))
, строковый литерал, как в (QUOTE "abc")
, или любой другой тип литерала. На этапе чтения читатель будет читать форму в виде списка (назовите его form1 ), первым элементом которого является символ QUOTE
, а вторым элементом является объект x ', чей текстовое представление x . Обратите внимание, что я специально говорю, что объект x ' хранится в списке, который представляет выражение , т.е. в некотором смысле он хранится как часть кода сама .
Теперь очередь за оценщиком. Вводом оценки является form1 , который является списком. Таким образом, он смотрит на первый элемент form1 и, определив, что это символ QUOTE
, , возвращает в качестве результата вычисления второй элемент списка . Это решающий момент. Оценщик возвращает второй элемент списка, который должен быть оценен, это то, что читатель прочитал на первом этапе выполнения (до компиляции!). Это все, что он делает. В этом нет магии, он очень прост и, что важно, новые объекты не создаются и не копируются существующие.
Поэтому, когда вы изменяете «цитируемый список», вы изменяете сам код . Самомодифицирующийся код - очень запутанная вещь, и в этом случае его поведение фактически не определено (поскольку ANSI Common Lisp позволяет реализациям помещать код в постоянную память).
Конечно, вышесказанное - просто ментальная модель. Реализации могут свободно реализовывать модель различными способами, и на самом деле я не знаю ни одной реализации Common Lisp, которая, как и мое объяснение, вообще не компилируется. Тем не менее, это основная идея.