修改文字列表时应该出错吗?

Should I be getting an error when modifying a literal list?

下面的示例代码出现在 R5RS(第 26 页)和 R7RS-small(第 41 页)中。

(define (g) '(constant-list))
(set-car! (g) 3)  ; Error.

标准规定在尝试修改文字列表时应该出现错误。但是,当我在 MIT Scheme 11.2、Chez Scheme 9.5、Guile Scheme 3.0.1 和 Racket 7.2 (plt-r5rs) 中尝试 运行 上述代码时,完全没有错误。是我的理解不正确,还是所有这些 Scheme 实现都不符合 R5RS 和 R7RS-small?

底线是你误读了标准,但这是完全可以理解的。

R6RS方案

Chez 方案是 R6RS。在 section 5.10 中,R6RS 标准说(强调我的):

An attempt to store a new value into a location referred to by an immutable object should raise an exception with condition type &assertion.

但在 Chapter 2 of R6RS 中,“应该”一词的含义是为标准的目的而定义的:

should
This word, or the adjective “recommended”, means that valid reasons may exist in particular circumstances to ignore a statement, but that the implications must be understood and weighed before choosing a different course.

这意味着实现可以选择在遇到修改不可变对象的尝试时是否引发异常。这与 The Scheme Programming Language 中所说的一致,该语言由 Kent Dybvig(Chez Scheme 的创建者)撰写,他也是 R6RS 的编辑之一。这段话继续强调,即使没有引发异常,对不可变对象的修改也会导致未指定的行为:

Quoted and self-evaluating constants are immutable. That is, programs should not alter a constant via set-car!, string-set!, etc., and implementations are permitted to raise an exception with condition type &assertion if such an alteration is attempted. If an attempt to alter an immutable object is undetected, the behavior of the program is unspecified.

在R6RS Scheme中,这种情况下不需要引发异常。 Chez Scheme 是 R6RS 的一个实现。

R7RS 方案

在 R7RS 标准的第 3.4 节中,围绕不可变对象的讨论对语言进行了一些更改(恢复为 R5RS 语言):

It is an error to attempt to store a new value into a location that is denoted by an immutable object.

但是第 1.3.2 节讨论了错误报告要求:

When speaking of an error situation, this report uses the phrase “an error is signaled” to indicate that implementations must detect and report the error.

set-car! 的文档显示了这个例子:

(define (g) ’(constant-list))
(set-car! (g) 3) ⇒ error

但是它没有说“发出错误信号”。上面的例子简单地说明了左边的表单的评估导致了错误;在这种情况下,实现不需要检测错误并发出错误信号。

即使其他实现没有,在这种情况下,Chibi Scheme(这是 R7RS 的 事实上的 参考实现)似乎确实会引发错误:

> (define (g) '(1 2 3))
> (g)
(1 2 3)
> (set-car! (g) 0)
ERROR on line 3: set-car!: immutable pair: (1 2 3)

R7RS Scheme 在本实例中与 R5RS 具有完全相同的语言,set-car! 的示例也是相同的。因此,当尝试使用 set-car! 更改列表文字时,R7RS 和 R5RS 都不需要实现引发错误,即使这样做是错误的,并且这样做会导致未指定的行为。