Range Redesign: Empty Ranges
Paul Backus
snarwin at gmail.com
Thu Mar 7 23:15:02 UTC 2024
On Thursday, 7 March 2024 at 18:32:50 UTC, Steven Schveighoffer
wrote:
> I meant the latter. A concrete range type.
>
> How does it happen? Consider that an array is a concrete type
> that people use all the time. Why should any other range be
> different? I've definitely stored ranges and other things as
> type members that were voldemort types.
This doesn't answer my question.
There are lots of ways in which (built-in) arrays are different
from other types of ranges. Most notably, an array can be used as
either a range or a container. There are plenty of use-cases for
creating an empty container.
What I am asking, specifically, is whether there is any use-case
where *generic code*, given a range of some arbitrary type `R`,
needs to create another range which both (a) has the exact
concrete type `R`, and (b) is empty. Since that's the feature
that's being proposed here.
(Non-generic code does not need this feature to be part of the
range API, because it can rely on specific features of whatever
concrete type it's working with.)
> This ability is more of a question of "do we want to add this
> feature to ranges or not?" The feature doesn't currently exist
> -- you can't assume that an uninitialized range is empty.
If there are no use-cases for this feature, then the answer to
"do we want to add it" ought to be "no." That's why I'm asking
about use-cases.
> Sometimes, we are bitten by the fact that the array is the most
> common range, and behaves in a specific way. People depend on
> that mechanism without realizing it, and then sometime later,
> they decide to change the type to one that is very compatible
> with arrays, but offers some benefit (i.e. to remove an
> allocation). However, the new range type might behave in
> unexpected ways, *but still compiles*.
This is a general problem with templates/macros compared to typed
generics. Even if we get rid of this particular edge case, there
are still dozens more that users are going to run into if they
only test with arrays.
If we want to address this problem, I think the best thing we can
do is to provide a standard suite of test ranges that users can
plug into their code to uncover edge cases and bugs.
>> The main thing you lose by dropping support for reference-type
>> ranges is interfaces. In particular, the interface inheritance
>> hierarchy in `std.range.interfaces`, where `ForwardRange`
>> inherits from `InputRange` and so on, cannot really be
>> replicated using `structs` (`alias this` only goes so far).
>
> As mentioned, you can wrap these interfaces into structs, which
> then have better lifetime tracking capabilities.
How do you implement this with structs?
interface ForwardAssignable : InputAssignable!E,
ForwardRange!E
Interfaces allow multiple inheritance. Structs can only have one
`alias this` member. Maybe you're fine with giving up on this
feature, but let's at least be honest that we *are* giving up
features here.
More information about the Digitalmars-d
mailing list