On Tue, 13 May 2014 13:40:55 -0400, H. S. Teoh via Digitalmars-d <[email protected]> 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

Reply via email to