以下は、適切に編集された同じ質問に対する私の答えです:
悪い人
foo
is self-modifying code. This is extremely dangerous. While the variable lst
disappears at the end of the let
form, its initial value persists in the function object, and that is the value you are modifying. Remember that in Lisp a function is a first class object, which can be passed around (just like a number or a list), and, sometimes, modified. This is exactly what you are doing here: the initial value for lst
is a part of the function object and you are modifying it.
実際に何が起こっているかを見てみましょう:
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a b c)))) (delq e lst)))
(foo 'c)
==> (a b)
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a b)))) (delq e lst)))
(foo 'b)
==> (a)
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a)))) (delq e lst)))
(foo 'a)
==> nil
(symbol-function 'foo)
==> (lambda (e) (let ((lst (quote (a)))) (delq e lst)))
いいもの
bar
では、 lst
は新鮮なコンスセルに初期化されているので安全です。
bar
はそのコードを変更しません。
ボトムライン
一般に、引用されたデータを扱うのが最善です '(1)
のように定数を変更する - 変更しない
quote
は引数を評価せずに返します。 (quote x)
は x
を生成します。
警告: quote
は戻り値を構成しませんが、
Lispリーダーによって事前に構築された値(infoノードを参照)
印刷表現)。これは、(a。b)
が
と同じです(cons 'a' b)
:前者は短所ではありません。引用する必要があります
副作用によって決して変更されない定数のために予約され、
あなたが自己修正コードを好きでない限り。情報の共通の落とし穴を参照してください
予期しない結果の例については、再編成を参照してください。いつ
引用されたオブジェクトは変更されます。
リストを変更する必要がある場合は、 barのように quote
ではなく list
または cons
または copy-list
。
詳細 例を参照してください。
ps - 変数の名前付け
Emacs Lispは lisp-2 なので、これらは変数 lst
の代わりに list
。