Flux
Flux

Reputation: 10910

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

The example code below appears in both R5RS (page 26) and R7RS-small (page 41).

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

The standards say that there should be an error when trying to modify a literal list. However, when I tried to run the code above in MIT Scheme 11.2, Chez Scheme 9.5, Guile Scheme 3.0.1, and Racket 7.2 (plt-r5rs), there is no error at all. Is my understanding incorrect, or are all these Scheme implementations non-compliant with both R5RS and R7RS-small?

Upvotes: 1

Views: 124

Answers (1)

ad absurdum
ad absurdum

Reputation: 21320

The bottom line is that you are misreading the Standards, but this is quite understandable.

R6RS Scheme

Chez Scheme is R6RS. In section 5.10 the R6RS Standard says (emphasis mine):

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

But in Chapter 2 of R6RS the meaning of the word "should" is defined for the purposes of the Standard:

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.

This means that implementations may choose whether or not to raise an exception when encountering an attempt to modify an immutable object. This aligns with what is said in The Scheme Programming Language, which was written by Kent Dybvig (the creator of Chez Scheme) who was also one of the editors of R6RS. The passage goes on to emphasize that modification of immutable objects results in unspecified behavior, even when no exception is raised:

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.

In R6RS Scheme, there is no requirement to raise an exception in this case. Chez Scheme is an implementation of R6RS.

R7RS Scheme

In Section 3.4 of the R7RS Standard, the language has been changed a bit (reverted to the R5RS language) around the discussion of immutable objects:

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

But Section 1.3.2 discusses error reporting requirements:

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.

The documentation for set-car! does show this example:

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

But nowhere does it say that "an error is signalled". The above example simply illustrates that evaluation of the form on the left results in an error; the implementation is not required to detect and signal an error in this case.

Even if other implementations do not, it does seem that Chibi Scheme (which is something of a de facto reference implementation for R7RS) raises an error in this case:

> (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 has exactly the same language as R5RS in this instance, and the example for set-car! is the same. So neither R7RS nor R5RS require implementations to raise an error when an attempt is made to alter a list literal with set-car!, even though it is an error to do so and doing so results in unspecified behavior.

Upvotes: 2

Related Questions