digitalmars.D.learn - RefRange
- David (3/3) Aug 26 2012 It's a RefRange, but not completly ... Can somebody explain me that
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (49/52) Aug 26 2012 According to its documentation, RefRange works differently whether the
- David (4/57) Aug 26 2012 Yes, that does it, but .save doesn't play well with RefRange (a static
- Jonathan M Davis (12/15) Aug 26 2012 refRange simply returns the original range if it's an input range rather...
- Jonathan M Davis (11/27) Aug 26 2012 Though the fact that you ran into this issue may indicate that having re...
- Era Scarecrow (23/25) Aug 26 2012 That brings up my own question. I'm writing an application that
- Jonathan M Davis (10/42) Aug 27 2012 I don't think that I really understand the question, but I'd be worried ...
- Era Scarecrow (9/19) Aug 27 2012 Well the first block actually holds size information and the
- David (6/33) Aug 26 2012 Ranges died another time for me. This refRange copy thingy cost me lots
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (7/10) Aug 26 2012 What version of dmd? What is the code?
- David (7/17) Aug 26 2012 DMD 2.059 and:
- David (1/1) Aug 26 2012 Sorry, dmd 2.060
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (3/4) Aug 26 2012 Hmmm. I use 2.060 as well.
It's a RefRange, but not completly ... Can somebody explain me that behaviour? http://dpaste.dzfl.pl/643de2a3
Aug 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/643de2a3According 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
Aug 26 2012
Am 26.08.2012 18:06, schrieb Ali Çehreli:On 08/26/2012 08:41 AM, David wrote: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).It's a RefRange, but not completly ... Can somebody explain me that behaviour? http://dpaste.dzfl.pl/643de2a3According 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
Aug 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/643de2a3refRange 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
Aug 26 2012
On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote:On Sunday, August 26, 2012 17:41:45 David wrote: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 DavisIt's a RefRange, but not completly ... Can somebody explain me that behaviour? http://dpaste.dzfl.pl/643de2a3refRange 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.
Aug 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); } }
Aug 26 2012
On Sunday, August 26, 2012 23:20:49 Era Scarecrow wrote:On Sunday, 26 August 2012 at 18:07:27 UTC, Jonathan M Davis wrote:I don't think that I really understand the question, but I'd be worried about intermixing save with operating on a range as an output range. It _should_ work, but save was designed with reading in mind, not writing. An output range doesn't have to have save or even front or popFront. All it needs is to work with put. Output ranges are a very different beast from input ranges, even if input ranges can be output ranges. That being said, I'd expect that save would save the current state, and any writing to the original would not affect the saved range. - Jonathan M DavisBut 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); } }
Aug 27 2012
On Monday, 27 August 2012 at 20:46:18 UTC, Jonathan M Davis wrote:I don't think that I really understand the question, but I'd be worried about intermixing save with operating on a range as an output range. It _should_ work, but save was designed with reading in mind, not writing. An output range doesn't have to have save or even front or popFront. All it needs is to work with put. Output ranges are a very different beast from input ranges, even if input ranges can be output ranges. That being said, I'd expect that save would save the current state, and any writing to the original would not affect the saved range.Well the first block actually holds size information and the information it holds is the old information, stuff may have been added or taken away, so hopefully not to have to do two passes (a dummy pass and then a real one) I was hoping save would save the location. If it doesn't reference the previous location using the current data then I'll need to figure something out. It's this that's been holding off one of my projects for a while as I'm not sure how to best approach it.
Aug 27 2012
Am 26.08.2012 20:07, schrieb Jonathan M Davis:On Sunday, August 26, 2012 10:17:13 Jonathan M Davis wrote: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!On Sunday, August 26, 2012 17:41:45 David wrote: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 DavisIt's a RefRange, but not completly ... Can somebody explain me that behaviour? http://dpaste.dzfl.pl/643de2a3refRange 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.
Aug 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
Aug 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)); AliDMD 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.
Aug 26 2012
On 08/26/2012 02:46 PM, David wrote:Sorry, dmd 2.060Hmmm. I use 2.060 as well. Ali
Aug 26 2012