2011-12-31 33 views
4

我揣摩的东西野趣方案中发生:计划 - 定义列表VS符号

(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中建立新的列表,第二个我们没有。但我不明白它是如何实际工作的。方案在第二个foo中定义地址,并做什么?它是否也被定义为第二个foo中的列表?或符号?

谢谢。

+0

您使用的是什么翻译方案?我无法在Racket中重现这种行为 - 因为它迫使我总是使用'mlist'来创建可变列表,因为'(abc)语法生成不可变列表 – 2011-12-31 13:37:18

+0

@ÓscarLópez:我使用Dr.Scheme或chezScheme – 2011-12-31 13:41:57

+0

这是一个旧版本现在称为Racket,并且在许多其他新事物中,它禁止列表的变化,除非列表被明确声明为可变。也许你发现了一个错误?我建议你尝试与球拍,如果它没有太多的麻烦 – 2011-12-31 13:49:18

回答

3

直接列表('(foo bar baz),而不是(list 'foo 'bar 'baz))是not allowed to be mutated。如果这样做,那“是一个错误”(即行为未定义)。

在这种情况下,您正在观察的是文字'(he said:)正在被反复重复使用,并且理解它不会发生变异。既然你违反了这种理解,你会看到你看到的奇怪行为。

与此相反,当您使用(list 'he 'said:)时,每次都会返回一个新列表。