4 ms·
Ranges and Suffering
- jasone 5y agoThis is an interesting, if long, take on Rust's ranges and some of their creaky design elements. I found it particularly interesting due to having recently researched Rust's ranges while adding ranges to my own programming language project. A few remarks from my perspective outside the Rust mindset: - 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).
- sillysaurusx 5y ago> If ranges are immutable, referentially transparent, those problems go away. 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.
- lalaithion 5y agoYou could make Range<T> copy if T is copy, which would tell the compiler “feel free to automatically copy this, move it into registers, or put it on the stack”, which basically makes it usable as a “value type” with no ownership semantics.
- sillysaurusx 5y agoCan you? If so, what’s the point of this article? Something doesn’t add up.
- lalaithion 5y agoSorry, the “you” in the article isn’t referring to what an individual rust programmer could do, but what the rust language designers could do.
- dbaupp 5y agoA distinct notion of “immutable” and “referentially transparent” are somewhat less useful in Rust, ownership essentially means most objects/types have the useful aspects of those properties by default (e.g http://smallcultfollowing.com/babysteps/blog/2018/02/01/in-rust-ordinary-vectors-are-values/ http://smallcultfollowing.com/babysteps/blog/2018/02/01/in-r... ). 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.
- waffle_maniac 5y agoI didn't know there's a gay TLD.
- brundolf 5y agoI'll be honest, it's never even occurred to me to use ranges for anything but iteration. And doing so feels out of scope, at least from the way they were designed in Rust (as the author illustrates). 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.