Jump to page: 1 2
Thread overview
RefRange
Aug 26, 2012
David
Aug 26, 2012
Ali Çehreli
Aug 26, 2012
David
Aug 26, 2012
Jonathan M Davis
Aug 26, 2012
Jonathan M Davis
Forward Range(s)
Aug 26, 2012
Era Scarecrow
Aug 27, 2012
Jonathan M Davis
Aug 28, 2012
Era Scarecrow
Aug 26, 2012
David
Aug 26, 2012
Ali Çehreli
Aug 26, 2012
David
Aug 26, 2012
David
Aug 26, 2012
Ali Çehreli
August 26, 2012
It's a RefRange, but not completly ... Can somebody explain me that behaviour?

http://dpaste.dzfl.pl/643de2a3
August 26, 2012
On 08/26/2012 08:41 AM, David wrote:
> It's a RefRange, but not completly ... Can somebody explain me that
> behaviour?
>
> http://dpaste.dzfl.pl/643de2a3

According to its documentation, RefRange works differently whether the original range is a ForwardRange or not:

  http://dlang.org/phobos/std_range.html#refRange

I have made TestRange a ForwardRange but then I had to comment out two lines of your program. Does it work according to your expectations with this change?

import std.stdio;
import std.range;

struct TestRange {
    float[] x = [0, 1, 2, 3, 4, 5];

    @property bool empty() {
        return x.length == 0;
    }

    @property ref float front() {
        return x[0];
    }

    void popFront() {
        //writefln("before: %s", x);
        x = x[1..$];
        //x.popFront();
        //writefln("after: %s", x);
    }

    TestRange save() @property {
        return TestRange(x);
    }
}



void main() {
    static assert(isForwardRange!TestRange);

    TestRange r = TestRange();
    auto rr = refRange(&r);

    //    foreach(element; rr) {}

    //    writefln("Original range: %s", r.x);
    //    writefln("RefRange: %s", rr.x);

    writefln("%s - %s", r.x.ptr, r.x.ptr);

    rr.popFront();

    writefln("%s - %s", r.x.ptr, r.x.ptr);
    writefln("Original range: %s", r.x);
    // We can't expect the RefRange to have the members of the original range
    // writefln("RefRange: %s", rr.x);

    r.popFront();

    writefln("%s - %s", r.x.ptr, r.x.ptr);
    writefln("Original range: %s", r.x);
    // We can't expect the RefRange to have the members of the original range
    // writefln("RefRange: %s", rr.x);
}

Ali
August 26, 2012
On Sunday, August 26, 2012 17:41:45 David wrote:
> It's a RefRange, but not completly ... Can somebody explain me that behaviour?
>
> http://dpaste.dzfl.pl/643de2a3

refRange simply returns the original range if it's an input range rather than a forward range, since normally, when you have an input range, it isn't a value type, and there's no way to copy it, so operating on one reference of it is already the same as operating on all of them, making RefRange pointless.

However, you've done the odd thing of declaring a value type input range. I don't know why that would ever be done except through ignorance of how ranges work. So, refRange is actually returning a copy in your case, which is why you're having problems.

And by the way, the only reason that rr.x works is because refRange is returning a copy rather than a RefRange!TestRange.

- Jonathan M Davis
August 26, 2012
On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote:
> On Sunday, August 26, 2012 17:41:45 David wrote:
> > It's a RefRange, but not completly ... Can somebody explain me that behaviour?
> > 
> > http://dpaste.dzfl.pl/643de2a3
> 
> refRange simply returns the original range if it's an input range rather than a forward range, since normally, when you have an input range, it isn't a value type, and there's no way to copy it, so operating on one reference of it is already the same as operating on all of them, making RefRange pointless.
> 
> However, you've done the odd thing of declaring a value type input range. I don't know why that would ever be done except through ignorance of how ranges work. So, refRange is actually returning a copy in your case, which is why you're having problems.

Though the fact that you ran into this issue may indicate that having refRange return the original if it isn't a forward range was a bad decision. I don't know. In the normal case, it's definitely better, because it avoids an unnecessary wrapper, but obviously, people can make mistakes. You should still be able use RefRange with an input range though, as long as you use it directly.

auto wrapped = RefRange!TestRange(&orig);

But it would be better IMHO to just fix it so that your range is a forward range, since there's no reason for it not to be.

- Jonathan M Davis
August 26, 2012
On Sunday, 26 August 2012 at 18:07:27 UTC, Jonathan M Davis wrote:
> But it would be better IMHO to just fix it so that your range is a forward range, since there's no reason for it not to be.

 That brings up my own question. I'm writing an application that will end up using an output range (likely an appender, so semi-dynamic). How will I be sure that what's passed to other functions will append to the range? And more importantly, if I use save and then rewrite an earlier section (due to updated information) would that also be correct assuming memory didn't change on it? Can you give an example?

 Currently my code goes something like this:

 struct ... {
  innerType[] someInnerType;

  void write(T)(T outputRange)
  if(isForwardRange!(T)){

   auto firstBlock = outputRange.save;
   //write to outputRange, first output will be re-written
   writeFirstBlock(outputRange);

   foreach(ref i; someInnerType) {
    i.write(outputRange);
   }

   //updated information for first block
   writeFirstBlock(save);
  }
 }


August 26, 2012
Am 26.08.2012 20:07, schrieb Jonathan M Davis:
> On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote:
>> On Sunday, August 26, 2012 17:41:45 David wrote:
>>> It's a RefRange, but not completly ... Can somebody explain me that
>>> behaviour?
>>>
>>> http://dpaste.dzfl.pl/643de2a3
>>
>> refRange simply returns the original range if it's an input range rather
>> than a forward range, since normally, when you have an input range, it
>> isn't a value type, and there's no way to copy it, so operating on one
>> reference of it is already the same as operating on all of them, making
>> RefRange pointless.
>>
>> However, you've done the odd thing of declaring a value type input range. I
>> don't know why that would ever be done except through ignorance of how
>> ranges work. So, refRange is actually returning a copy in your case, which
>> is why you're having problems.
>
> Though the fact that you ran into this issue may indicate that having refRange
> return the original if it isn't a forward range was a bad decision. I don't
> know. In the normal case, it's definitely better, because it avoids an
> unnecessary wrapper, but obviously, people can make mistakes. You should still
> be able use RefRange with an input range though, as long as you use it
> directly.
>
> auto wrapped = RefRange!TestRange(&orig);
>
> But it would be better IMHO to just fix it so that your range is a forward
> range, since there's no reason for it not to be.
>
> - Jonathan M Davis
>

Ranges died another time for me. This refRange copy thingy cost me lots of time, then I tried to implement a .save method, which uhm, just didn't work together with RefRange (isForwardRange!T succeeded, but isForwardRange!(RefRange!T) failed).

Anyways, thanks for your explanations!
August 26, 2012
Am 26.08.2012 18:06, schrieb Ali Çehreli:
> On 08/26/2012 08:41 AM, David wrote:
>> It's a RefRange, but not completly ... Can somebody explain me that
>> behaviour?
>>
>> http://dpaste.dzfl.pl/643de2a3
>
> According to its documentation, RefRange works differently whether the
> original range is a ForwardRange or not:
>
>    http://dlang.org/phobos/std_range.html#refRange
>
> I have made TestRange a ForwardRange but then I had to comment out two
> lines of your program. Does it work according to your expectations with
> this change?
>
> import std.stdio;
> import std.range;
>
> struct TestRange {
>      float[] x = [0, 1, 2, 3, 4, 5];
>
>      @property bool empty() {
>          return x.length == 0;
>      }
>
>      @property ref float front() {
>          return x[0];
>      }
>
>      void popFront() {
>          //writefln("before: %s", x);
>          x = x[1..$];
>          //x.popFront();
>          //writefln("after: %s", x);
>      }
>
>      TestRange save() @property {
>          return TestRange(x);
>      }
> }
>
>
>
> void main() {
>      static assert(isForwardRange!TestRange);
>
>      TestRange r = TestRange();
>      auto rr = refRange(&r);
>
>      //    foreach(element; rr) {}
>
>      //    writefln("Original range: %s", r.x);
>      //    writefln("RefRange: %s", rr.x);
>
>      writefln("%s - %s", r.x.ptr, r.x.ptr);
>
>      rr.popFront();
>
>      writefln("%s - %s", r.x.ptr, r.x.ptr);
>      writefln("Original range: %s", r.x);
>      // We can't expect the RefRange to have the members of the original
> range
>      // writefln("RefRange: %s", rr.x);
>
>      r.popFront();
>
>      writefln("%s - %s", r.x.ptr, r.x.ptr);
>      writefln("Original range: %s", r.x);
>      // We can't expect the RefRange to have the members of the original
> range
>      // writefln("RefRange: %s", rr.x);
> }
>
> Ali

Yes, that does it, but .save doesn't play well with RefRange (a static assert inside RefRange fails, telling that the produced RefRange-Type is not a ForwardRange).
August 26, 2012
On 08/26/2012 02:21 PM, David wrote:

> I tried to implement a .save method, which uhm, just
> didn't work together with RefRange (isForwardRange!T succeeded, but
> isForwardRange!(RefRange!T) failed).

What version of dmd? What is the code?

When I add the following lines to the beginning of main() of the program that I have used in my other post, they both pass:

    static assert(isForwardRange!TestRange);
    static assert(isForwardRange!(RefRange!TestRange));

Ali

August 26, 2012
Am 26.08.2012 23:33, schrieb Ali Çehreli:
> On 08/26/2012 02:21 PM, David wrote:
>
>  > I tried to implement a .save method, which uhm, just
>  > didn't work together with RefRange (isForwardRange!T succeeded, but
>  > isForwardRange!(RefRange!T) failed).
>
> What version of dmd? What is the code?
>
> When I add the following lines to the beginning of main() of the program
> that I have used in my other post, they both pass:
>
>      static assert(isForwardRange!TestRange);
>      static assert(isForwardRange!(RefRange!TestRange));
>
> Ali
>

DMD 2.059 and: https://github.com/Dav1dde/BraLa/blob/7440688038bfd50a06fd9a49b8e9b6d08c7b4c28/brala/utils/queue.d

But I don't care anylonger, I rewrote the whole Queue class (now it's a "real" queue, e.g. you can wait until all items are used up, with core.sync.condtion), I also don't feel like wasting more time in ranges, when I don't need them.
August 26, 2012
Sorry, dmd 2.060
« First   ‹ Prev
1 2