www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Make std.container.Array an output range

reply "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
I depend heavily on RAII in a project I'm working on. Since 
structs in dynamic arrays never have their destructors called I'm 
using Array!T instead. A pattern that comes up often is that I 
have some input range of T's which need to be stored in a member 
Array!T. However Array is not an output range so I can't use

inputRange.copy(someArray);

I understand the difference between a container and a range 
iterating over that container. However I do think a container is 
an output range.

Should I file an enhancement request or is there something 
fundamentally wrong with this idea? For Array it should be as 
simple as adding

alias doPut = insertBack;
Jun 05 2014
next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 5 June 2014 at 13:51:35 UTC, Rene Zwanenburg wrote:
 I depend heavily on RAII in a project I'm working on. Since 
 structs in dynamic arrays never have their destructors called 
 I'm using Array!T instead. A pattern that comes up often is 
 that I have some input range of T's which need to be stored in 
 a member Array!T. However Array is not an output range so I 
 can't use

 inputRange.copy(someArray);

 I understand the difference between a container and a range 
 iterating over that container. However I do think a container 
 is an output range.

 Should I file an enhancement request or is there something 
 fundamentally wrong with this idea? For Array it should be as 
 simple as adding

 alias doPut = insertBack;

Well, one issue is that for a "Range", "put" really just means overwrite the front element, and pop it. So... Array!int myArray = ...: copy([1, 2, 3], myArray); //(1) copy([1, 2, 3], myArray[]); //(2) In this situation, (1) and (2) would have different meaning. This whole mess comes from "Writeable InputRange" being considered an OutputRange... Arguably, an OutputRange should be nothing more than a "sink", which an InputRange is not.
Jun 05 2014
prev sibling next sibling parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Thursday, 5 June 2014 at 16:21:21 UTC, monarch_dodra wrote:
 Well, one issue is that for a "Range", "put" really just means 
 overwrite the front element, and pop it. So...

 Array!int myArray = ...:
 copy([1, 2, 3], myArray);   //(1)
 copy([1, 2, 3], myArray[]); //(2)

 In this situation, (1) and (2) would have different meaning.

Just to clarify, I think that means that MAKING Array an output range is a bad idea, for the same reasons that vector is not an output iterator. That said, having an explicit OutputRange adapator: struct BackInserter(Container) { Container* c; void put(T)(ref T t) { c.insertBack(t); } } auto backInserter(Container)(ref Container c) { return BackInserter!Container(&c); } Useage: inputRange.copy(someArray.backInserter()); There: Clear and un-ambiguous.
 Should I file an enhancement request or is there something 
 fundamentally wrong with this idea? For Array it should be as 
 simple as adding

 alias doPut = insertBack;


doPut is not a range primitive. Implementing "doPut" on your container should have no effect. If it does, it is a bug and will *quickly* be fixed. Don't count on it working. The correct primitive is "put".
Jun 05 2014
prev sibling next sibling parent "Rene Zwanenburg" <renezwanenburg gmail.com> writes:
On Thursday, 5 June 2014 at 16:29:09 UTC, monarch_dodra wrote:
 On Thursday, 5 June 2014 at 16:21:21 UTC, monarch_dodra wrote:
 Well, one issue is that for a "Range", "put" really just means 
 overwrite the front element, and pop it. So...


I see. I wasn't aware of that.
 That said, having an explicit OutputRange adapator:

 struct BackInserter(Container)
 {
     Container* c;
     void put(T)(ref T t)
     {
         c.insertBack(t);
     }
 }
 auto backInserter(Container)(ref Container c)
 {
     return BackInserter!Container(&c);
 }


 Useage:
 inputRange.copy(someArray.backInserter());

 There: Clear and un-ambiguous.

Agreed. This is much nicer.
 Should I file an enhancement request or is there something 
 fundamentally wrong with this idea? For Array it should be as 
 simple as adding

 alias doPut = insertBack;


doPut is not a range primitive. Implementing "doPut" on your container should have no effect. If it does, it is a bug and will *quickly* be fixed. Don't count on it working. The correct primitive is "put".

Thanks. I skimmed the documentation for std.range.put a bit too fast :). Reading it more carefully I see it also mentions your first point regarding front + popFront.
Jun 05 2014
prev sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
05-Jun-2014 17:51, Rene Zwanenburg пишет:
 I depend heavily on RAII in a project I'm working on. Since structs in
 dynamic arrays never have their destructors called I'm using Array!T
 instead. A pattern that comes up often is that I have some input range
 of T's which need to be stored in a member Array!T. However Array is not
 an output range so I can't use

 inputRange.copy(someArray);

 I understand the difference between a container and a range iterating
 over that container. However I do think a container is an output range.

 Should I file an enhancement request or is there something fundamentally
 wrong with this idea? For Array it should be as simple as adding

 alias doPut = insertBack;

I think we all understand that not every container has one and holy insertion policy. How about adding Array.backInserter ? -- Dmitry Olshansky
Jun 06 2014