引用のメンタル モデルに欠陥がある可能性があるという観察結果は素晴らしいものです。ただし、そのメンタル モデルが何であるかによって、当てはまる場合と当てはまらない場合があります。
まず、プログラムの実行にはさまざまな段階があることを覚えておいてください。Lisp 環境は、最初にプログラム テキストをデータ構造 (リスト、シンボル、および文字列や数値などのさまざまなリテラル データ) に読み込まなければなりません。次に、それらのデータ構造をマシンコードまたは何らかの中間フォーマットにコンパイルする場合としない場合があります。最後に、結果のコードが評価されます(もちろん、マシン コードの場合、これは単に適切なアドレスにジャンプすることを意味する場合があります)。
ここではコンパイルの問題を脇に置き、評価者の入力がリーダーによって読み取られるデータ構造のリストであると (簡単にするために) 仮定して、読み取りと評価の段階に焦点を当てましょう。
xがオブジェクトのテキスト表現である(QUOTE x)
フォームを考えてみましょう。これは、 のようなシンボル リテラル、 のようなリスト リテラル、のような文字列リテラル、またはその他の種類のリテラルです。読み取り段階では、リーダーはフォームをリスト ( form1と呼びます) として読み取ります。最初の要素はシンボルで、2 番目の要素はオブジェクトx'で、テキスト表現はxです。オブジェクトx'は、式を表すリスト内に格納されている、つまり、ある意味では、コード自体の一部として格納されていると具体的に言っていることに注意してください。(QUOTE ABC)
(QUOTE (A B C))
(QUOTE "abc")
QUOTE
今度は評価者の番です。エバリュエーターの入力は、リストであるform1です。そのため、 form1の最初の要素を見てQUOTE
、それが symbol であると判断すると、評価の結果として list の 2 番目の要素を返します。これが重要なポイントです。エバリュエーターは、評価されるリストの 2 番目の要素を返します。これは、リーダーが最初の実行段階 (コンパイル前!) で読み取ったものです。 それだけです。 これには魔法はなく、非常に単純です。重要なことに、新しいオブジェクトが作成されたり、既存のオブジェクトがコピーされたりすることはありません。
したがって、「引用符付きリスト」を変更すると、コード自体が変更されます。自己変更コードは非常に紛らわしいものであり、この場合の動作は実際には定義されていません (ANSI Common Lisp では実装がコードを読み取り専用メモリに置くことを許可しているため)。
もちろん、上記は単なるメンタルモデルです。実装は、さまざまな方法でモデルを自由に実装できます。実際、私の説明のように、コンパイルをまったく行わない Common Lisp の実装を私は知りません。それでも、これが基本的な考え方です。