Is this range behaviour correct?

Ali Çehreli acehreli at yahoo.com
Thu Mar 14 20:44:50 PDT 2013


On 03/14/2013 04:58 PM, Jesse Phillips wrote:
> On Thursday, 14 March 2013 at 21:40:34 UTC, Ali Çehreli wrote:
>> I had toyed with the idea of making a ForwardRange from an InputRange
>> by caching the elements. Without any guarantees, :) here is the code:
>>
>> http://forum.dlang.org/thread/ifg5ei$2qc7$1@digitalmars.com
>>
>> Ali
>
> I attempted to create a sliceable forward range from an input range. I
> think I ran into a problem of keeping the buffer in sync when doing
> lookahead.
>
> list2 = list1.save();
>
> while(true) {
> list1.popFront();
> list2.popFront();
>
> assert(list1.front == list2.front);
> }
>
> What happens when your buffer needs to fill, how do you get the data in
> list 1 & 2? I'm not posing this question as impossible only something to
> make work.

I had to study that old code of mine to understand how it works. :)

The popFront() on the range itself dispatches the call to 
ForwardRangeLazyCache by providing the id of this "view". In a sense, it 
says "the range with this id would like to pop an element":

     @property void popFront()
     {
         lazyCache.popFront(myId);
     }

ForwardRangeLazyCache.popFront simply increments the pointer of the 
range that is associated with that id:

     void popFront(size_t id)
     {
         ++(viewPtrs[id]);
     }

I am not sure whether this is a good idea but the actual filling of the 
cache and synchronizing the "views" happen in front():

     @property immutable(E) front(size_t id)
     {
         ensureRead(viewPtrs[id]);
         return *(viewPtrs[id]);
     }

The above says "ensure that the element that this view is trying to 
access is in the cache", and then returns that element. It looks like 
there is even some optimization if the array elements have not been moved:

     void ensureRead(immutable(E) * ptr)
     {
         if (ptr == endPtr) {
             immutable oldPtr = cache.ptr;
             cache ~= range.front.idup;
             range.popFront();

             if (cache.ptr != oldPtr) {
                 /* The cache has been relocated */
                 adjustPtrs(oldPtr, cache.ptr);

             } else {
                 ++endPtr;
             }
         }
     }

etc. :) I am really not sure whether it works correctly. :/

Ali


More information about the Digitalmars-d-learn mailing list