"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