我试图弄清楚在Scheme中发生的事情:
(define last-pair
(lambda (x)
(if (null? (cdr x))
x
(last-pair (cdr x)))))
当我以这种方式定义foo时:
(define foo
(lambda ()
(let ((s (list 'he 'said:)))
(set-cdr! (last-pair s)
(list 'ha 'ha))
s)))
并且运行foo 3次,我得到了:
(he said: ha ha)
(he said: ha ha)
(he said: ha ha)
但是当我以这种方式定义foo时:
(define foo
(lambda ()
(let ((s '(he said:)))
(set-cdr! (last-pair s)
(list 'ha 'ha))
s)))
并且运行foo 3次,我得到了:
(he said: ha ha)
(he said: ha ha ha ha)
(he said: ha ha ha ha ha ha)
但为什么呢?我的第一个想法是,我们在第一个foo
中建立了新的列表,而在第二个我们没有。但我不明白它是如何运作的。 Scheme在第二个foo
中定义地址,并做什么?它是否也在第二个foo中定义为列表?还是一个符号?
感谢。
答案 0 :(得分:3)
文字列表('(foo bar baz)
,而不是(list 'foo 'bar 'baz)
)是not allowed to be mutated。如果你这样做,“这是一个错误”(即行为未定义)。
在这种情况下,您所观察到的是文字'(he said:)
被反复使用,并且理解它不会变异。由于你违反了这种理解,你会得到你所看到的奇怪行为。
相反,当您使用(list 'he 'said:)
时,每次都会返回一个新列表。