"isDroppable" range trait for slicing to end

monarch_dodra monarchdodra at gmail.com
Wed Oct 31 03:37:13 PDT 2012


On Wednesday, 31 October 2012 at 08:58:18 UTC, Jonathan M Davis 
wrote:
>
> I agree, but for that to be realistic, I think that issue# 7177 
> needs to be
> implemented first. You should check out the pull request that I 
> have for
> improving hasSlicing. I just updated it according to some of 
> the discussion
> here, and it now checks the behavior of opDollar when it works 
> with the range
> being sliced. For finite ranges, it essentially enforces that 
> they function
> like arrays do, and for infinite ranges, it comes as close to 
> that as it can:
>
> https://github.com/D-Programming-Language/phobos/pull/854
>
> As of the latest state of that pull request, hasSlicing looks 
> like
>
> template hasSlicing(R)
> {
>     enum bool hasSlicing = !isNarrowString!R && is(typeof(
>     (inout int _dummy=0)
>     {
>         R r = void;
>
>         static if(isInfinite!R)
>             typeof(take(r, 1)) s = r[1 .. 2];
>         else
>             R s = r[1 .. 2];
>
>         s = r[1 .. 2];
>
>         static if(is(typeof(r[0 .. $])))
>         {
>             R t = r[0 .. $];
>             t = r[0 .. $];
>
>             static if(!isInfinite!R)
>             {
>                 R u = r[0 .. $ - 1];
>                 u = r[0 .. $ - 1];
>             }
>         }
>
>         static assert(isForwardRange!(typeof(r[1 .. 2])));
>         static assert(hasLength!(typeof(r[1 .. 2])));
>     }));
> }
>
>
> - Jonathn M Davis

I'm not a huge fan of the "opDollar" check, because essentially, 
it doesn't really buy you anything: if hasSlicing!R, then is "r = 
r[1..$]" legal? Who knows! You as a developer need to check 
manually that "r[0 .. $]" is legal first anyways...

Under those circumstances, why not cleanly splice the two notions?

//----
template hasSlicing(R)
{
     enum bool hasSlicing = !isNarrowString!R && is(typeof(
     (inout int _dummy=0)
     {
         R r = void;

         static if(isInfinite!R)
             typeof(take(r, 1)) s = r[1 .. 2];
         else
             R s = r[1 .. 2];

         s = r[1 .. 2];

         static assert(isForwardRange!(typeof(r[1 .. 2])));
         static assert(hasLength!(typeof(r[1 .. 2])));
     }));
}

template hasSlicingToEnd(R)
{
     enum bool hasSlicingToEnd = !isNarrowString!R && is(typeof(
     (inout int _dummy=0)
     {
         R r = void;

         static if(is(typeof(r[0 .. $])))
         {
             R t = r[0 .. $];
             t = r[0 .. $];

             static if(!isInfinite!R)
             {
                 R u = r[0 .. $ - 1];
                 u = r[0 .. $ - 1];
             }
         }
     }));
}
//----

IMO, this makes a clean distinction between both "types" of 
slicing. An added bonus is that (for now) it also correctly 
supports finite RA ranges that don't define opDollar.


//----
PS: Do we really have to force that infinite slice to be of a 
type of "take"? Does that mean we can't imagine an infinite range 
that defines it's own finite slice type?

if we change the code to:

//----
         static if(isInfinite!R)
             auto s = r[1 .. 2]; //HERE1
         else
             R s = r[1 .. 2];

         s = r[1 .. 2]; //HERE2
//----

Then we force nothing on the slice's type (HERE1), but do verify 
that subsequent slices will be assignable back to the original 
slice (HERE2)...


More information about the Digitalmars-d mailing list