1

sbclとclispを使用した次の単純なプログラムで異なる結果が得られる理由を誰かが説明できますか?私がしていることは言語によって定義されていないのですか、それとも2つのLispインタープリターの1つが間違っていますか?

; Modify the car of the passed-in list
(defun modify (a) (setf (car a) 123))

; Create a list and print car before and after calling modify
(defun testit () (let ((a '(0)))
                   (print (car a))
                   (modify a)
                   (print (car a))))
(testit)

SBCL(バージョン1.0.51)は以下を生成します:

0 
0 

CLISP(バージョン2.49)は(私が期待するもの)を生成します:

0 
123 
4

1 に答える 1

2

この動作はリテラルデータの変更によるものであるという点で、SethとVsevolodのコメントに同意します。(list 0)の代わりに使用してみてください'(0)。これに関する質問は比較的頻繁に出てくるので、ここでHyperSpecを引用します。

3.7.1リテラルオブジェクトの変更

リテラルオブジェクトが破壊的に変更された場合の結果は未定義です。

「リテラル」の定義:

文字通りの調整 (オブジェクトの)プログラムによって計算されるのではなく、プログラム内で直接参照されます。つまり、引用符形式のデータとして表示されます。オブジェクトが自己評価オブジェクトの場合は、引用符で囲まれていないデータとして表示されます。「(cons "one"'( "two"))の形式では、式 "one"、( "two")、および"two"はリテラルオブジェクトです。」

多くの場合(多くの実装では)、リテラル値を変更すると、コード自体で実際に変更されることに注意してください。つまり、自己変更コードを記述します。サンプルコードは期待どおりに機能しません。

CCLのサンプルコード:

CL-USER> (defun modify (a) (setf (car a) 123))
MODIFY
CL-USER> (defun testit ()
           (let ((a '(0)))
             (print (car a))
             (modify a)
             (print (car a))))
TESTIT
CL-USER> (testit)

0 
123 
123
CL-USER> (testit)

123 
123 
123

の2番目の評価を見てくださいtestit。ここで、letそれ自体にはすでに変更された値が含まれているため、最初の評価でprintもが得られ123ます。

Lisp、短所、および(数値。数値)の違いも参照してください。これについて詳しく説明したか、上記のVsevolodのコメントにリンクされている質問です。

于 2012-04-28T20:29:22.910 に答える