10/31/2012 10:37 AM, monarch_dodra пишет:
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...

That's a temporary thing because otherwise it'll break all of current RA. The idea is that if there is $ then it's tested

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.

Jonathon's version also supports RA without 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)...

Well I'd rather never check that infinite range has 1..2 form of slicing to begin with. If we have some that do then we'd have to keep it.

--
Dmitry Olshansky

Reply via email to