www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Problem with using struct ranges with disabled this(this) with some

reply "Uranuz" <neuranuz gmail.com> writes:
As far as I understand to save current cursor of forward range I 
should always use *save* property. But sometimes range struct is 
just copied using postblit without using save (it happens even in 
Phobos). Is it correct behaviour to *pass ownership* for range 
structs via just copying of range or not. As I think for at least 
*forward* ranges that are structs we must always use save methot 
to store new cursor. But for *input* ranges it is not possible, 
so there maybe plain copying could be allowed. I thing that we 
should work out some descision on this problem, provide some 
unittests for different types of ranges with and without postblit 
for standard Phobos functions and fix them accordingly.

I have problem with std.range.take function and forward range 
with disabled postblit and I don't understand is it my or library 
bug?
Sep 01 2015
parent reply "Mike Parker" <aldacron gmail.com> writes:
On Wednesday, 2 September 2015 at 06:28:52 UTC, Uranuz wrote:
 As far as I understand to save current cursor of forward range 
 I should always use *save* property. But sometimes range struct 
 is just copied using postblit without using save (it happens 
 even in Phobos). Is it correct behaviour to *pass ownership* 
 for range structs via just copying of range or not. As I think 
 for at least *forward* ranges that are structs we must always 
 use save methot to store new cursor. But for *input* ranges it 
 is not possible, so there maybe plain copying could be allowed. 
 I thing that we should work out some descision on this problem, 
 provide some unittests for different types of ranges with and 
 without postblit for standard Phobos functions and fix them 
 accordingly.

 I have problem with std.range.take function and forward range 
 with disabled postblit and I don't understand is it my or 
 library bug?
My understanding is that one underlying assumption in Phobos about ranges is that they are lightweight and single-minded -- they should carry no state other than what is necessary to fulfill the range interface they provide. This follows from the idea that, given a container, you do not slap a range interface on the container type and pass container instances to range-based functions, but instead implement a range type separate from the container that knows where the elements of the container begin and end and nothing else. They do not carry the elements of the container around with them. Looking at ranges from that angle, the need to disable postblit on a range type would be a special case. That raises the question, for what reason have you disabled postblit on your range type? Is it not possible for you to create a lightweight range from your data?
Sep 02 2015
parent reply "Uranuz" <neuranuz gmail.com> writes:
On Wednesday, 2 September 2015 at 07:34:15 UTC, Mike Parker wrote:
 On Wednesday, 2 September 2015 at 06:28:52 UTC, Uranuz wrote:
 As far as I understand to save current cursor of forward range 
 I should always use *save* property. But sometimes range 
 struct is just copied using postblit without using save (it 
 happens even in Phobos). Is it correct behaviour to *pass 
 ownership* for range structs via just copying of range or not. 
 As I think for at least *forward* ranges that are structs we 
 must always use save methot to store new cursor. But for 
 *input* ranges it is not possible, so there maybe plain 
 copying could be allowed. I thing that we should work out some 
 descision on this problem, provide some unittests for 
 different types of ranges with and without postblit for 
 standard Phobos functions and fix them accordingly.

 I have problem with std.range.take function and forward range 
 with disabled postblit and I don't understand is it my or 
 library bug?
My understanding is that one underlying assumption in Phobos about ranges is that they are lightweight and single-minded -- they should carry no state other than what is necessary to fulfill the range interface they provide. This follows from the idea that, given a container, you do not slap a range interface on the container type and pass container instances to range-based functions, but instead implement a range type separate from the container that knows where the elements of the container begin and end and nothing else. They do not carry the elements of the container around with them. Looking at ranges from that angle, the need to disable postblit on a range type would be a special case. That raises the question, for what reason have you disabled postblit on your range type? Is it not possible for you to create a lightweight range from your data?
I want to understand if we have *save* method in Forward Range then why or in which cases we should use plain struct copying instead. Should we assume that these two ways are equal or not? Also as far as I understand behaviour for Input Ranges vs Forward Ranges would be different, because you could not store cursor on object like network data stream, because as soon as you read from it you cannot save some range that will point on previous bytes in network stream, because they are gone if you read them. So for Input Range copy will always point on current state, but not previois state, that was saved before in another range pointing to the same source. For Forward Range we have ability to save cursor position and return to it later. In this case would copying via postblit would be equal to *save* method or would be similar as for Input Range.
Sep 02 2015
parent anonymous <anonymous example.com> writes:
On Wednesday 02 September 2015 09:52, Uranuz wrote:

 I want to understand if we have *save* method in Forward Range
 then why or in which cases we should use plain struct copying
 instead. Should we assume that these two ways are equal or not?
No, don't assume that they're the same.
 Also as far as I understand behaviour for Input Ranges vs Forward
 Ranges would be different, because you could not store cursor on
 object like network data stream, because as soon as you read from
 it you cannot save some range that will point on previous bytes
 in network stream, because they are gone if you read them.
 
 So for Input Range copy will always point on current state, but
 not previois state, that was saved before in another range
 pointing to the same source.
A copy of an input range may reflect the original, but it may also become invalid when the original is touched. Any operation on the original (especially popFront) may leave the copy in an invalid state, and vice versa. That means, when you make a copy of an input range, you should not use the original anymore.
 For Forward Range we have ability to save cursor position and
 return to it later. In this case would copying via postblit would
 be equal to *save* method or would be similar as for Input Range.
Can go either way. Copying a forward range may work like a call to `save`, but it's not guaranteed/required to. When you need the behavior of `save`, call `save`. Do not assume that copying works like `save`. Do also not assume that a copy and the original of a range update each other correctly. When you pass an input range to some function and you want the operation to affect the original, use std.range.refRange to pass a reference.
Sep 02 2015