range behaviour

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Tue May 13 11:17:52 PDT 2014


On Tue, 13 May 2014 13:40:55 -0400, H. S. Teoh via Digitalmars-d  
<digitalmars-d at puremagic.com> wrote:

> On Tue, May 13, 2014 at 01:29:32PM -0400, Steven Schveighoffer via  
> Digitalmars-d wrote:
> [...]

>> In any case, I think generic code for an unknown range type in an
>> unknown condition should have to call empty, since it cannot logically
>> prove that it's not.
> [...]
>
> In my mind, *all* range-based code is generic. If you need to depend on
> something about your range beyond what the range API guarantees, then
> you should be using the concrete type rather than a template argument,
> which means that your code is no longer range-based code -- it's
> operating on a concrete type.

You can be generic, but still know that empty is not necessary.

This is a potential use case (somewhat similar to yours):

void foo(R)(R r)
{
    if(!r.empty)
    {
       auto r2 = map!(x => x.bar)(r); // or some similar translation range
       // have to check r2.empty here? The "empty must be called" rules say  
yes.
    }
}

I will note, there are cases in phobos that don't check empty because it's  
provably not necessary.

The issue arose because of the filter range, which someone was trying to  
make fully lazy. The whole thrust of the argument is that we want to force  
people to call empty not because we want them to write generically safe  
code but because we want to *instrument* empty to do something other than  
check for emptiness. In other words, if we are guaranteed that empty will  
be called before anything else, we can add extra bits to empty for e.g.  
lazy initialization. Otherwise, we have to add the bits to all the  
primitives.

It also results in an awkward call when it's not strictly necessary:

r2.empty;

-Steve


More information about the Digitalmars-d mailing list