"isDroppable" range trait for slicing to end

Dmitry Olshansky dmitry.olsh at gmail.com
Mon Oct 29 12:14:48 PDT 2012


29/10/2012 14:33, monarch_dodra пишет:
> More often than not, we want to slice a range all the way to the end,
> and we have to use the clumsy "r[0 .. r.length]" syntax.

That supposed to be r[].

>
> What's worst is that when a range is infinite, there is no real way to
> "slice to the end", unless you just repeatedly popFront.

Slice to the end was meant to be this:
r[x..$]

>
> This is a real shame, because a lot of infinite ranges (sequence, cycle,
> repeat, ...) support random access, but not slice to end. They *could*
> slice to end if the language allowed it.

The real shame is a compiler bug that prevented $ from ever working 
except in a few special cases. (that and special meaning of length 
inside of []).

>
> --------
> I'd like to introduce a new primitive: "popFrontN". You may recognize
> this as a standalone function if range.d: It is. I propose we improve
> this semantic by allowing ranges to directly implement this function
> themselves. Then, popFrontN will defer to that function's
> implementation. This would allow certain infinite ranges (such as
> sequence) to provide a popFrontN implementation, even though they aren't
> sliceable.
>

Introducing new things as part of range definition (capability) is a 
costly move. Paying that cost to address a vague special case - not 
worth it.

>  From there, I'd like to introduce a new trait "isDroppable": This trait
> will answer true if a range naturally supports the popFrontN primitive
> (or is already sliceable).
>
> --------
> So what makes this so interesting? Not only does it give new performance
> possibilities, it also unlocks new possibilities for the implementation
> of algorithms:

Where? I thought it was about unlocking certain pattern for infinite RA 
ranges, not that much of benefit elsewhere.

> A LOT of algorithm take a special quick route when the input ranges are
> sliceable, random access, and hasLength. Blatant examples of this are
> "find", "copy", or as a general rule, anything that iterates on two
> ranges at once. The thing though is that they never actually *really*
> require sliceability, nor querying length. All they want is to be able
> to write "return r[i .. r.length]", but "return r.drop(i)" would work
> *just* as well.

Your drop(i) would still have to know length for anything finite.

TBH all stuff that is (if ever) specialized in std.algorithm:
a) tries to optimize with strings
b) tries to optimize with arrays
c) sometimes catches general RA or slicing

I'm pushing 2 things of c) type in one pull, yet I don't see it as a 
common thing at all, e.g. presently copy doesn't care about RA/slicing, 
only for built-in arrays.

Most of the time things are "downgraded" to Input/ForwardRange
and worked from that - simple, slow and generic.

> --------
> Another thing which makes this "isDropable" notion interesting is that
> the dropped range guarantees the returned range's type is that of the
> original ranges, unlike hasSlicing, which doesn't really guarantee it:
> some infinite ranges can be sliced, but the returned slice (obviously)
> is not infinite...

Interesting. I'm thinking that simply defining an opDollar to return 
special marker type and overloading opSlice should work:

struct InfRange{
...
EndMarker opDollar();
InfRange opSlice(size_t start, EndMarker dummy);
SomeOtherRangeType opSlice(size_t start, size_t end);
...
}

And if you omit second overload it doesn't have normal slicing.
isDropable then tests specifically slicing with dollar.

-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list