Creating a Sub-view of a non - RA (hasSlicing) range.

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Sat Jun 30 16:51:37 PDT 2012


On 6/30/12 11:15 AM, Monarch Dodra wrote:
> On Saturday, 30 June 2012 at 14:22:06 UTC, Andrei Alexandrescu wrote:
>>> 2) The new range is defined as a fixed length from the beginning of the
>>> range, as opposed to start and finish points. If I were to insert new
>>> items into my Slist, the new range would just bump the top items out of
>>> its range.
>>
>> SList's range is not defined by start and finish points. It's defined
>> as the start point, and the finish point is implicit by use of a
>> sentinel (the null pointer).
> Well, what about in the case of a BidirRange from a BDList? Surelly, it
> would be defined by a start and finish point?

Yes. But now you're moving the goalposts because many of your arguments 
referred to SList.

> Take, on the other hand, creates a range, which is defined by a start
> point, and a fixed length. Inserting elements into the middle of the
> original list would bump elements out of the "take range", which remains
> fixed sized.

Correct. take() and takeExactly() work under the assumption there's no 
surreptitious change in the structure of the range underneath. I think 
that's a reasonable decision.

> On the other hand, had I manually shrunk my BDlistRange until it was 5
> elements long, and then inserted elements into the midle of the list, it
> would cause my BDListRange to grow, and nothing to drop out of it.

Right. Generally ranges are not responsible for accurately tracking 
underlying structural changes. There will always be ways to mess up 
things in ways that leave extant ranges unsynchronized.

>> Not sure I understand this, but when we get into the realm of bidir
>> ranges, things get a fair amount better. How would TakeLast work?
>
> Well, if we forget Slist, and just focus on a standard
> BidirectionalRange, say comming from a DList. Things don't really get
> any better, because take still returns just a ForwardRange.

Which is as it should be. How would you otherwise take the first n 
elements of a given doubly-linked list in constant time?

> There is no way of doing, say:
>
> BidirectionalRange aBD = ...;
>
> //Create subrange...
> //aBD = take(aBD, 5); //Error, wrong type
> auto subrange = take(aBD, 5);
>
> if(subrange.back == 5) //Error, subrange does not have a back method.
> //...But that's strange, because aBD IS a bidiretinal range
>
> Since the Take Range it is defined by a begining point and a length,
> there is no way it could give Bidir access.

It's all about what it takes to reach a certain point. You are sensing 
something indeed, but take() is not it. The problem is there's no simple 
way to count 5 starting from the left side of a doubly-linked list, stop 
there, and then create a range from the beginning of the list and that 
mid point. In C++, that's trivial because range ends are separate.

> ----
> I came to D after reading your talk on ranges, and I really liked (and
> am still enjoying) the concept. However, with C++, when you iterate over
> [First, Last), you are also creating a two new ranges: [First, Current)
> & [Current, Last). D doesn't provide that, it only provides a way to
> shrink the current range and create [Current, Last).

Yes, that's a good way of putting it.

> Using range, you don't get [First, Current). At best, you only get
> a)A forward range only
> b)A fixed size range
> c)A range of another type

We could extend the range interface for specific ranges to allow for 
such. However, there hasn't been a strong need so far.


Andrei


More information about the Digitalmars-d mailing list