10

からのこの一節On Lispは本当に紛らわしいです - などの引用符で囲まれたリストを返すと、実際に関数が将来'(oh my)どのように動作するかを実際に変更する方法が明確ではありません: 返されたリストは関数でゼロから再度生成されますか?呼ばれた?

戻り値に引用符付きリストが組み込まれるように exclaim を定義すると、

(defun exclaim (expression) 
  (append expression ’(oh my)))

その後、戻り値の破壊的な変更

(exclaim ’(lions and tigers and bears)) 
->  (LIONS AND TIGERS AND BEARS OH MY)
(nconc * ’(goodness))
->  (LIONS AND TIGERS AND BEARS OH MY GOODNESS)

関数内のリストを変更できます。

(exclaim ’(fixnums and bignums and floats)) 
->  (FIXNUMS AND BIGNUMS AND FLOATS OH MY GOODNESS)

このような問題に対する明確な証拠を作成するには、次のように記述します。

(defun exclaim (expression)
  (append expression (list ’oh ’my)))

exclaim結果に単語を追加するための最後の呼び出しはどのくらい正確goodnessですか? 関数は外部変数を参照していないので、関数の動作をnconc実際に変更するための別の呼び出しはどのように行われたのでしょうか?exclaim

4

1 に答える 1

11

a)リテラルリストを変更した場合の影響は、Common Lisp 標準では定義されていません。ここで例として示しているのは、可能な動作の 1 つです。

(1 2 3 4)リテラルリストです。しかし、LISTlike を呼び出すと(list 1 2 3 4)、実行時に新たにコンスされたリストが返されます。

b) リストは、関数のコード内のリテラル データです。すべての呼び出しは、このデータ オブジェクトを正確に返します。呼び出しごとに新しいリストを提供したい場合は、LIST や COPY-LIST などを使用する必要があります。

c) 返されるリストは常に同じリテラル データ オブジェクトであるため、それを変更すると、説明したようにこの効果が生じる可能性があります。コードとそのオブジェクトが読み取り専用メモリに割り当てられている場合、エラーが発生することも想像できます。リストを変更すると、読み取り専用メモリに書き込もうとします。

d) ソース コードでリテラル リスト データを扱う場合に留意すべき点の 1 つは、Lisp コンパイラがストレージを自由に最適化できることです。リストがソース コードで複数回発生した場合、コンパイラはこれを検出し、1 つのリストのみを作成することができます。さまざまな場所のすべてが、この 1 つのリストを指します。したがって、リストを変更すると、これらの変更がいくつかの場所で表示される可能性があります。

これは、配列/ベクトルなどの他のリテラル データ オブジェクトでも発生する可能性があります。

データ構造がコードの一部である場合、この内部データ構造を返し、このデータ構造を変更してから、コードを変更しようとします。

Lisp はインタプリタによって実行できることにも注意してください。インタプリタは通常、Lisp ソース構造で動作します。コードはマシン コードではなく、Lisp コードを Lisp データとして解釈します。ここでは、ソース コードに埋め込まれたデータだけでなく、実行時にソース コードを変更できる場合があります。

于 2014-04-11T02:27:48.523 に答える