Ranges and Suffering
kaylynn.gay
kaylynn.gay
- An awful lot of the problems have to do with ownership semantics. If ranges are immutable, referentially transparent, those problems go away.
- The author suggests (in the "Where to from here" section) that ranges should be convertable to iterators, rather than inherently iterators themselves. In my experience this works very well. Ranges can always be integer-based, and, as long as the collection can efficiently be mapped onto integers, conversion to/from iterators is trivial.
- The notion of "directional" ranges seems ill-posed. As described, such a range would actually be more like a vector. Also, in a language which uses wrap-around integer types (modular arithmetic semantics), a "backwards" range is still well-defined and finite. For example, an 8-bit 6..3 range is 6..=255 + 0..3 (the complement of 3..6).
Do they though? Ultimately you need to store them somewhere. And oh look where we’re headed, choo choo last stop ownership semanticsville.
Though it would be interesting to just yeet it into the global static ether and leave it at that. I wonder if such a thing would’ve been possible in rust. It’s kind of funny when you think about it, that all this fuss is just to track two integers aka 16 bytes.
Still, at that point it wouldn’t be be a “global static” pool so much as a global pool.
The key issue with ranges and mutation is specifically that they’re an Iterator (rather than just convertible, as you reiterate from the post). It’s fine to be directly mutable, and allow updating the fields as desired.
I don't have any specific knowledge on the design process, but Rust ranges very much feel like they were intended to be "for-loops without manual state management, and also you can use them in iterator chains", with anything beyond that being gravy. It seems like the author is just asking to be frustrated by trying to use them for purposes they were never designed to serve.
And anyway- if the author wants to have Copy-able, instrospectable ranges that can be used to represent arbitrary numeric bounds and just happen to also support iteration, it should be trivial to implement that themselves:
#[derive(Copy, Clone)]
struct Range(i32, i32);
You could even have a `.to_range()` method that converts them into a standard Range. I think the author just needs to adjust their expectations around this particular standard construct.