On 2020-09-01 21:45 +0200, Marc Nieper-Wißkirchen wrote:
> I don't understand this argument. Some vectors are mutable, other
> vectors aren't mutable.
We seem to be replaying this discussion repeatedly. Let me take another approach.
A vector is a collection of locations (see R[57]RS section 3.3); a range as currently specified has no locations. This is a fundamental difference between the two data structures. Because both are indexed by a contiguous range of integers from 0 to a fixed value k, and because the time it takes to return the value v_i associated with an index i is constant (modulo caching issues), they are otherwise similar. But they are not interchangeable.
Note: An empty vector contains no locations, which is why (eqv? #() #()) may return either true or false.
The reason it's an error to mutate a vector element when the vector is a part of the program's AST is that Scheme systems are free to use locations to represent code but are not required to do so (except that closures have at least one associated location).
I understand the reason for why there is this restriction in the R7RS for vector literals. The relevant conclusion is that there are vectors, which are immutable (in the sense that it is an error to mutate them) and so any procedure taking vector arguments has to cope with them (e.g. by specifying that the vector argument may be mutated).
Exactly the same procedures that make sense for vector literals make sense for ranges.
> This is irrelevant for any observable behavior of a program.]
Observable behavior is not in itself sufficient to specify a program's semantics. Behavior that can never be observed also matters.
Can you clarify in what sense the latter is relevant here?
Is there a significant advantage to allowing ranges and vectors to
be the same type, potentially?
I don't see any, since you can't count on it, and since some procedures on vectors cannot be performed on ranges.
Particular implementations can give you the guarantee, or a future SRFI. At the moment, nothing would change but enabling potential future guarantees.
The second half-sentence cannot be that relevant as the same set of procedures on vectors cannot be performed on all vectors.
On the topic of mutability: since
ranges are now an abstract type,
I don't see what's abstract about it; it i
s as concrete as integers (which may also have more than one representation internally).
and no longer a (bound, length, indexer) triple,
It's a (length, indexer) pair, explicitly so in the `range` constructor, and implicitly so in the other constructors. For example, (vector-range vec) is
equivalent to (range (vector-length vec) (lambda (n) (vector-ref vec n))). I agree that the range-indexer accessor isn't very useful, but that doesn't mean it is undefined.
Not talking about mutable ranges here but the indexer as a procedure is not well-defined (unless you create it on the fly through a closure containing range-ref). But that's not a bad thing.
It would be a leaky abstraction if, instead, the SRFI prescribed that all range constructors have to go through the range constructor.
Marc