2

アクセサー関数nthの使用に問題があります。リストをいくつかの関数に渡し、 nthを使用して関数内のリストの要素に新しいバインディングを作成します。次に、関数からリストを呼び出すと、リストが変更され、それは私が望むものではありません! 何が起こるのですか?

いくつかの例

(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1

上記のことは理解できますが、すべてをリストに変更すると、理解できないことが起こります

(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)

a は (1) であると予想していましたが、なぜ変更されたのですか? carfirstなどの他の機能も試しましたが、結果は同じです。

PS、Lispworks と SBCL で試してみましたが、同じ結果でした。

4

3 に答える 3

4
(defun test (x) (incf x)) => TEST
(setq a 1) => 1
(test a) => 2
a => 1

に渡し1ますtest。test 内で、ローカル変数を変更しましたxaは変更されておらず、そのように変更することはできません。a参照ではない値を に渡しますa

(defun test (x) (incf (nth 0 x))) => TEST
(setq a '(1)) => (1)
(test a) => 2
a => (2)

テストするリスト(1)を渡します。リストはコピーされません。ローカル変数xは、リスト内の最初のコンス セルを指します。次に、最初のコンス セルのcarを 2 に変更します。リストはコピーされないので、渡されたリストを変更します。aまた、そのリストの最初のコンス セルを指します。それもそう(2)です。

于 2012-12-24T10:11:53.177 に答える
3

何も変更したくない場合は、を使用しないでくださいincf。を使用し1+ます。使用する唯一の理由incfは、その副作用が必要なためです。

これが発生する理由については、関数に渡される前に引数が評価されます。1で呼び出すtesta、値1が渡されますが、これは変更できません。リストに解決するとき、破壊的な機能を使用することを選択した場合は、ショップ全体aにリストを渡すことができます。setf

于 2012-12-24T10:19:07.530 に答える