digitalmars.D - std.array.put doesn't put
- Paul D. Anderson (20/20) Mar 01 2010 I've entered this as a Phobos bug, but wanted to be sure I was understan...
- Lars T. Kyllingstad (12/43) Mar 01 2010 I don't think it's a bug, I think it's just that arrays aren't that
- Robert Jacques (5/45) Mar 01 2010 Yes, it's not a bug. If you think of a common usage of arrays (buffers) ...
- Philippe Sigaud (32/46) Mar 02 2010 from std.range
- Paul D. Anderson (4/52) Mar 02 2010 Thanks (to all) for the clarification. I was wondering how such a big mi...
- Steve Teale (3/8) Mar 02 2010 That's exactly how I felt when I discovered this gem of clarity and
- Philippe Sigaud (2/9) Mar 03 2010 Now, repeat after me: retro is a good name, retro is a good name...
I've entered this as a Phobos bug, but wanted to be sure I was understanding this properly (i.e., this is a bug, right?): From the description of the put primitive in std.range: "r.put(e) puts e in the range (in a range-dependent manner) and advances to the popFront position in the range. Successive calls to r.put add elements to the range. put may throw to signal failure." From the example of std.array for the put function: void main() { int[] a = [ 1, 2, 3 ]; int[] b = a; a.put(5); assert(a == [ 2, 3 ]); assert(b == [ 5, 2, 3 ]); } So, "putting" 5 into the array a removes the first element in a, and changes the value of the first element of b. I would expect the first assert in the code above to read: assert(a == [ 5, 1, 2, 3 ]); The implementation of std.array.put doesn't make sense: void put(T, E)(ref T[] a, E e) { assert(a.length); a[0] = e; a = a[1 .. $]; } It modifies a[0] and then replaces the array with the tail of the array, omitting the first element. It's possible there is some arcane meaning to the word "put" that I'm not aware of, but if it means "insert an element at the front of the range" then std.array.put is wrongly implemented. Paul
Mar 01 2010
Paul D. Anderson wrote:I've entered this as a Phobos bug, but wanted to be sure I was understanding this properly (i.e., this is a bug, right?): From the description of the put primitive in std.range: "r.put(e) puts e in the range (in a range-dependent manner) and advances to the popFront position in the range. Successive calls to r.put add elements to the range. put may throw to signal failure." From the example of std.array for the put function: void main() { int[] a = [ 1, 2, 3 ]; int[] b = a; a.put(5); assert(a == [ 2, 3 ]); assert(b == [ 5, 2, 3 ]); } So, "putting" 5 into the array a removes the first element in a, and changes the value of the first element of b. I would expect the first assert in the code above to read: assert(a == [ 5, 1, 2, 3 ]); The implementation of std.array.put doesn't make sense: void put(T, E)(ref T[] a, E e) { assert(a.length); a[0] = e; a = a[1 .. $]; } It modifies a[0] and then replaces the array with the tail of the array, omitting the first element. It's possible there is some arcane meaning to the word "put" that I'm not aware of, but if it means "insert an element at the front of the range" then std.array.put is wrongly implemented. PaulI don't think it's a bug, I think it's just that arrays aren't that useful as output ranges. It has to be defined that way for it to adhere to the range interface conventions. (Think of the array as a file instead, then it makes more sense.) You just have to keep a backup slice of the entire array so you can access the elements you have put() later: int[] a = [0, 0, 0, 0, 0, 0]; int[] aSlice = a[]; foreach (i; 0 .. a.length) aSlice.put(i); assert (a == [0, 1, 2, 3, 4, 5]); -Lars
Mar 01 2010
On Mon, 01 Mar 2010 16:51:41 -0500, Lars T. Kyllingstad <public kyllingen.nospamnet> wrote:Paul D. Anderson wrote:Yes, it's not a bug. If you think of a common usage of arrays (buffers) this makes perfect sense. And if you want the other behavior you're supposed to use the appender wrapper.I've entered this as a Phobos bug, but wanted to be sure I was understanding this properly (i.e., this is a bug, right?): From the description of the put primitive in std.range: "r.put(e) puts e in the range (in a range-dependent manner) and advances to the popFront position in the range. Successive calls to r.put add elements to the range. put may throw to signal failure." From the example of std.array for the put function: void main() { int[] a = [ 1, 2, 3 ]; int[] b = a; a.put(5); assert(a == [ 2, 3 ]); assert(b == [ 5, 2, 3 ]); } So, "putting" 5 into the array a removes the first element in a, and changes the value of the first element of b. I would expect the first assert in the code above to read: assert(a == [ 5, 1, 2, 3 ]); The implementation of std.array.put doesn't make sense: void put(T, E)(ref T[] a, E e) { assert(a.length); a[0] = e; a = a[1 .. $]; } It modifies a[0] and then replaces the array with the tail of the array, omitting the first element. It's possible there is some arcane meaning to the word "put" that I'm not aware of, but if it means "insert an element at the front of the range" then std.array.put is wrongly implemented. PaulI don't think it's a bug, I think it's just that arrays aren't that useful as output ranges. It has to be defined that way for it to adhere to the range interface conventions. (Think of the array as a file instead, then it makes more sense.) You just have to keep a backup slice of the entire array so you can access the elements you have put() later: int[] a = [0, 0, 0, 0, 0, 0]; int[] aSlice = a[]; foreach (i; 0 .. a.length) aSlice.put(i); assert (a == [0, 1, 2, 3, 4, 5]); -Lars
Mar 01 2010
On Mon, Mar 1, 2010 at 22:51, Lars T. Kyllingstad <public kyllingen.nospamnet> wrote:Paul D. Anderson wrote:from std.range"r.put(e) puts e in the range (in a range-dependent manner) and advancesto the popFront position in the range. Successive calls to r.put add elements to the range. put may throw to signal failure."with std.array.put:It modifies a[0] and then replaces the array with the tail of the array,It seems to me array.put does what the description in std.range entails. I had the same reaction when reading array.put for the first time. How can a function putting values in something make them non-accessible at the same time? But that's because for arrays the container and the associated range (view) are the same, leading to some confusion. put puts values not in the range as said in std.range but in the container accessed by the range. The range itself updates in the only way a range can: by shrinking (so, popFront), giving you a new place to put a another value. As Lars said, a classical use would be: Container c = new Container(values); auto view =c.asOutputRange(); // view is an output range. Andrei suggested '.all' as a property returning a range on all values. foreach(elem; view) view.put(someOtherValues); // writes values in c, consumes view. assert(view.empty); // Now view is exhausted and c contains someOtherValues.omitting the first element.For some ranges, you can replace the front value: range.front = someValue; But then, how would you go putting some more? You cannot extend a range, I think. You can create a new range chaining new values and the old range, but that creates a new one. auto prepended = chain(newValues, oldValues); I think I have somewhere something inspired by zippers ( http://en.wikipedia.org/wiki/Zipper_%28data_structure%29), where a range 'remembers' previous values (stores them in an array) and you can make the front retreat, giving access to old values anew. But it cannot modify the sublying container, only the values stored (artificially) in the range. It's useful for some algorithms that need to go back and forth on a few positions. PhilippeIt's possible there is some arcane meaning to the word "put" that I'm not aware of, but if it means "insert an element at the front of the range" then std.array.put is wrongly implemented.
Mar 02 2010
Lars T. Kyllingstad Wrote:Paul D. Anderson wrote:Thanks (to all) for the clarification. I was wondering how such a big mistake could go unnoticed. :-) I will check into a range re-education camp until my mind is enlightened. PaulI've entered this as a Phobos bug, but wanted to be sure I was understanding this properly (i.e., this is a bug, right?): From the description of the put primitive in std.range: "r.put(e) puts e in the range (in a range-dependent manner) and advances to the popFront position in the range. Successive calls to r.put add elements to the range. put may throw to signal failure." From the example of std.array for the put function: void main() { int[] a = [ 1, 2, 3 ]; int[] b = a; a.put(5); assert(a == [ 2, 3 ]); assert(b == [ 5, 2, 3 ]); } So, "putting" 5 into the array a removes the first element in a, and changes the value of the first element of b. I would expect the first assert in the code above to read: assert(a == [ 5, 1, 2, 3 ]); The implementation of std.array.put doesn't make sense: void put(T, E)(ref T[] a, E e) { assert(a.length); a[0] = e; a = a[1 .. $]; } It modifies a[0] and then replaces the array with the tail of the array, omitting the first element. It's possible there is some arcane meaning to the word "put" that I'm not aware of, but if it means "insert an element at the front of the range" then std.array.put is wrongly implemented. PaulI don't think it's a bug, I think it's just that arrays aren't that useful as output ranges. It has to be defined that way for it to adhere to the range interface conventions. (Think of the array as a file instead, then it makes more sense.) You just have to keep a backup slice of the entire array so you can access the elements you have put() later: int[] a = [0, 0, 0, 0, 0, 0]; int[] aSlice = a[]; foreach (i; 0 .. a.length) aSlice.put(i); assert (a == [0, 1, 2, 3, 4, 5]); -Lars
Mar 02 2010
I will check into a range re-education camp until my mind is enlightened. PaulThat's exactly how I felt when I discovered this gem of clarity and Andrei enlightened me. Steve
Mar 02 2010
On Wed, Mar 3, 2010 at 06:52, Steve Teale <steve.teale britseyeview.com>wrote:Now, repeat after me: retro is a good name, retro is a good name...I will check into a range re-education camp until my mind is enlightened. PaulThat's exactly how I felt when I discovered this gem of clarity and Andrei enlightened me.
Mar 03 2010