Range Redesign: Copy Semantics

Paul Backus snarwin at gmail.com
Tue Jan 23 00:57:49 UTC 2024


On Monday, 22 January 2024 at 23:07:28 UTC, Jonathan M Davis 
wrote:
> In practice, basic input ranges don't work with the vast 
> majority of algorithms anyway. Some do (e.g. map), but pretty 
> much anything that needs to do more than a simple 
> transformation on the elements ends up needing a forward range. 
> I really don't think that we're going to lose much by forcing 
> basic input ranges to be separate.

Here's a very rough approximation of the number of algorithms in 
Phobos that work with basic input ranges:

     $ grep 'isInputRange' std/algorithm/*.d | wc -l
     153

For comparison, here are the other range types:

     $ grep 'isForwardRange' std/algorithm/*.d | wc -l
     141
     $ grep 'isBidirectionalRange' std/algorithm/*.d | wc -l
     42
     $ grep 'isRandomAccessRange' std/algorithm/*.d | wc -l
     62

So, I would say that your hypothesis is not supported by the 
data, in this case.

> Do they? Non-copyable types do not work with ranges right now. 
> They don't work with foreach right now. Non-copyable types have 
> their uses to be sure, but they're also fairly niche.

Work is being done to make ranges work with non-copyable types 
(e.g. [1]).

Foreach works if the elements are rvalues, or the elements are 
lvalues and you use ref for the loop variable. This is the 
correct, expected behavior.

I think a big part of the reason non-copyable types are not 
widely used is that a lot of existing library code was written 
without support for them in mind. Since we have an opportunity to 
start from scratch with Phobos v3, there is no reason to repeat 
this mistake.

[1] https://github.com/dlang/phobos/pull/8721

> trying to support non-copyable types will actively make 
> range-base code worse in many cases, because it will require 
> calling front multiple times, and many range-based algorithms 
> do real work in front rather than simply returning a value 
> (e.g. map works that way).

Have you ever actually written generic code that works with 
non-copyable types? I have, and it mostly involves (a) passing 
things by ref, (b) using 'auto ref' and core.lifetime.forward a 
lot, and (c) checking isCopyable!T before trying to copy things.

I have no idea why you think this would require calling front 
multiple times, or doing extra work. Perhaps you could try 
writing out some example code to clarify?

> Personally, I think that we should make it very explicit that 
> non-copyable types are not supported by ranges. They don't work 
> with them now, and I don't think that it's even vaguely worth 
> it to try to make ranges work with them. The cost is too high 
> for too little benefit.

First, as a general rule, I don't think that we, as 
standard-library authors, should be in the business of telling 
our users that their use-cases are illegitimate just because it 
makes our jobs more difficult.

Second...how do you know the benefit is too little? You thought 
earlier that "the vast majority of algorithms" didn't work with 
basic input ranges, even though the actual data shows that isn't 
true. Unless you have concrete evidence, I think it is better to 
avoid making assumptions about which use-cases are important and 
which aren't.


More information about the Digitalmars-d mailing list