cisco / ChezScheme

Chez Scheme
Apache License 2.0
6.95k stars 982 forks source link

Unclear documentation on vector constant (im)mutability #661

Open jltaylor-us opened 2 years ago

jltaylor-us commented 2 years ago

From the Chez Scheme google group mailer:

On Sep 6, 2022, at 3:31 AM, Peter Čerman [cerman.peter@gmail.com](mailto:cerman.peter@gmail.com) wrote: The next expression evaluates to #f: (equal? (let ((v '#(1 2 3))) (vector-set! v 1 100) v) '#(1 100 3))

Mutating a quoted constant is undefined behavior. See https://scheme.com/tspl4/objects.html#./objects:s2

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. An implementation may choose to share storage among different constants to save space.

The optimizer assumes it's a constant, and in this case determines that it is comparing two constant vectors and pre-computes the result:

> (expand/optimize '(equal? (let ((v '#(1 2 3))) (vector-set! v 1 100) v) '#(1 100 3))) (begin (#2%vector-set! '#(1 2 3) 1 100) #f)

The documentation is a bit confusing, though, since there is this statement in https://cisco.github.io/ChezScheme/csug9.5/objects.html#./objects:s34

All vectors are mutable by default, including constants. A program can create immutable vectors via vector->immutable-vector. Any attempt to modify an immutable vector causes an exception to be raised.

This is talking about immutable vectors, which is a distinct concept (introduced much more recently), and not related to the immutability described in the documentation for quote. It would be more accurate to say that while constant vectors can be mutated they should not be, and that it may have unexpected results. I'd say it's a bug in the documentation that these two concepts are not more clearly distinguished.

An alternative approach would be to make quoted vector constants immutable (as if with vector->immutable-vector), but that is a backwards incompatible change (and we tend to avoid those).

LiberalArtist commented 1 year ago

This is talking about immutable vectors, which is a distinct concept (introduced much more recently), and not related to the immutability described in the documentation for quote.

Is it really "not related"? AFAICT, the result of vector->immutable-vector has precisely the same restrictions on mutation as a quoted constant: the difference is whether Chez Scheme detects violations of such restrictions in safe mode. In particular, note that:

Chez Scheme Version 9.5.8
Copyright 1984-2022 Cisco Systems, Inc.

> (equal? (vector 1 2 3) (vector->immutable-vector (vector 1 2 3)))
#t

TSPL says "implementations are permitted to raise an exception with condition type &assertion" if there is an attempt to modify a quoted constant; R6RS § 5.10 says implementations "should":

It is desirable for constants (i.e. the values of literal expressions) to reside in read-only memory. To express this, it is convenient to imagine that every object that refers to locations is associated with a flag telling whether that object is mutable or immutable. Literal constants, the strings returned by symbol->string, records with no mutable fields, and other values explicitly designated as immutable are immutable objects, while all objects created by the other procedures listed in this report are mutable. An attempt to store a new value into a location referred to by an immutable object should raise an exception with condition type &assertion.

I would favor changing quoted constants to be immutable as with vector->immutable-vector unless there are significant compatibility problems in practice. In particular, the fact some documentation explicitly says that "the behavior of the program is unspecified" in such cases supplants the presumption in favor of preserving the current behavior for me.

Regardless, clearly https://cisco.github.io/ChezScheme/csug9.5/objects.html#./objects:s34 needs some change or clarification.