digitalmars.D.learn - Array slice length confusion
- Tim Matthews <tim.matthews7 gmail.com> Jul 07 2009
- Kagamin <spam here.lot> Jul 08 2009
- Kagamin <spam here.lot> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 08 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 08 2009
- Kagamin <spam here.lot> Jul 09 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 09 2009
- Daniel Keep <daniel.keep.lists gmail.com> Jul 09 2009
- grauzone <none example.net> Jul 09 2009
- "Steven Schveighoffer" <schveiguy yahoo.com> Jul 08 2009
- BCS <none anon.com> Jul 08 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 09 2009
- BCS <none anon.com> Jul 09 2009
- Tim Matthews <tim.matthews7 gmail.com> Jul 09 2009
- BCS <none anon.com> Jul 09 2009
First off if this has been asked so many times please just ignore this.
You should be able to collapse this whole subject in most good new
readers plus it is in d.learn out of the way so I expect no "ahh here we
go again" sort of replies.
Anyway I like how you can get a slice of array that is just a view into
the original. If I modify the slice, it modifies the full original array
which can be very useful. If however I modify the length of the slice
which I was doing in an attempt to extend the view, it becomes it's own
array.
This example should help explain what I mean:
module test;
import std.stdio;
void main()
{
char[5] a = "Hello";
char[] b;
b = a[1..3]; //b is a view into a
writeln(a); //(Hello)
writeln(b); //(el)
b[0] = 'a'; //no copy on write
writeln(a); //(Hallo)
writeln(b); //(al)
b.length = b.length+2; //COW on length change?
b[0] = 'z'; //does not modify a
writeln(a); //(Hallo)
writeln(b); //(zl)
}
Was this a design choice, bug, undefined behavior, etc...?
Jul 07 2009
Tim Matthews Wrote:Was this a design choice, bug, undefined behavior, etc...?
Design choice. In order to widen slice to should recreate it from the original array.
Jul 08 2009
Kagamin Wrote:Tim Matthews Wrote:Was this a design choice, bug, undefined behavior, etc...?
Design choice. In order to widen slice to should recreate it from the original array.
For this I use begin markers: ubyte[] buff=new ubyte[100]; int half=buff.length/2; ubyte[] buff1=buff[0..half]; ubyte[] buff2=buff[half..$];
Jul 08 2009
Kagamin wrote:For this I use begin markers: ubyte[] buff=new ubyte[100]; int half=buff.length/2; ubyte[] buff1=buff[0..half]; ubyte[] buff2=buff[half..$];
I actually think this has nothing to do with my OP.
Jul 08 2009
On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7 gmail.com> wrote:Was this a design choice, bug, undefined behavior, etc...?
design choice. A slice *is* an array in the current design. Increasing the length may or may not make a copy of it. An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it? The only exception is appending to a prefix slice. If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array: char[] str = "blah".dup; char[] sl = str[0..1]; sl ~= "r"; assert(str == "brah"); BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize -Steve
Jul 08 2009
Steven Schveighoffer wrote:On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7 gmail.com> wrote:Was this a design choice, bug, undefined behavior, etc...?
design choice. A slice *is* an array in the current design. Increasing the length may or may not make a copy of it. An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it? The only exception is appending to a prefix slice. If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array: char[] str = "blah".dup; char[] sl = str[0..1]; sl ~= "r"; assert(str == "brah"); BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize -Steve
I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi. Anyway if anyone gets here through a search engine the correct code assuming you can guarantee it is a slice and that doesn't go out of bounds. It is a systems language after all :) module test; import std.stdio; void resizeView(T)(ref T[] slice, size_t newLength) { (cast(size_t*)(&slice))[0] = newLength; } void main() { char[5] a = "hello"; char[] b = a[1..3]; writeln(a); //(hello) writeln(b); //(el) resizeView(b, b.length+1); writeln(a); //(hello) writeln(b); //(ell) }
Jul 08 2009
Steven Schveighoffer wrote:This is really not a good idea. You've removed one of the core features of the array -- memory safety. Doing this is just asking for memory corruption. You should either re-slice the original array, or create a type that has a reference to the original array so it can be resliced
I explicitly said that it was unsafe code and off course most situations would be better suited with the extra abstraction or re slice the original.
Jul 08 2009
Tim Matthews Wrote:I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.
Jul 09 2009
Kagamin wrote:Tim Matthews Wrote:I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.
Do you know the ng posts or where ever that was posted?
Jul 09 2009
Tim Matthews wrote:Kagamin wrote:Tim Matthews Wrote:I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.
Do you know the ng posts or where ever that was posted?
Best bet would be to search for "T[new]".
Jul 09 2009
Daniel Keep wrote:Tim Matthews wrote:Kagamin wrote:Tim Matthews Wrote:I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi.
Best bet would be to search for "T[new]".
Superseded by Andrei's Array struct.
Jul 09 2009
On Wed, 08 Jul 2009 23:09:52 -0400, Tim Matthews <tim.matthews7 gmail.com> wrote:Steven Schveighoffer wrote:On Wed, 08 Jul 2009 02:48:31 -0400, Tim Matthews <tim.matthews7 gmail.com> wrote:Was this a design choice, bug, undefined behavior, etc...?
A slice *is* an array in the current design. Increasing the length may or may not make a copy of it. An array slice doesn't know it was originally part of another array (i.e. there are no references back to the original array) so how would it know that there is data around it? The only exception is appending to a prefix slice. If a slice starts at the front of an allocated array, the runtime cannot tell that it was not the original array, so it clobbers data that was in the original array: char[] str = "blah".dup; char[] sl = str[0..1]; sl ~= "r"; assert(str == "brah"); BTW, all of this is defined behavior, see http://www.digitalmars.com/d/2.0/arrays.html#resize -Steve
I thought a slice would behave slighty different due to some sort of meta data that is a separate area of memory so it doesn't effect D's abi. Anyway if anyone gets here through a search engine the correct code assuming you can guarantee it is a slice and that doesn't go out of bounds. It is a systems language after all :) module test; import std.stdio; void resizeView(T)(ref T[] slice, size_t newLength) { (cast(size_t*)(&slice))[0] = newLength; } void main() { char[5] a = "hello"; char[] b = a[1..3]; writeln(a); //(hello) writeln(b); //(el) resizeView(b, b.length+1); writeln(a); //(hello) writeln(b); //(ell) }
This is really not a good idea. You've removed one of the core features of the array -- memory safety. Doing this is just asking for memory corruption. You should either re-slice the original array, or create a type that has a reference to the original array so it can be resliced: start with: struct TimSlice(T) { T[] slice; alias slice this; T[] srcArray; // override length property size_t length() {return slice.length;} void length(size_t) {/* use srcArray here to re-slice */} } This is assuming you are using D2, of course. With D1, it's more difficult. -Steve
Jul 08 2009
Hello Tim,Anyway I like how you can get a slice of array that is just a view into the original. If I modify the slice, it modifies the full original array which can be very useful. If however I modify the length of the slice which I was doing in an attempt to extend the view, it becomes it's own array.
Was this a design choice, bug, undefined behavior, etc...?
you can grab a larger chunk like this char[] buff1 = something; char[] buff2 = buff1[10..20]; buff2 = buff2.ptr[0..20]; note this is unsafe and will give you no warnings if you extend past the end of buff1;
Jul 08 2009
BCS wrote:Hello Tim,Anyway I like how you can get a slice of array that is just a view into the original. If I modify the slice, it modifies the full original array which can be very useful. If however I modify the length of the slice which I was doing in an attempt to extend the view, it becomes it's own array.
Was this a design choice, bug, undefined behavior, etc...?
you can grab a larger chunk like this char[] buff1 = something; char[] buff2 = buff1[10..20]; buff2 = buff2.ptr[0..20]; note this is unsafe and will give you no warnings if you extend past the end of buff1;
I know that but I when I said I was trying to extend the view I really mean that I was just trying to extend the view. Also depending on what news reader you use you should see that it branched off in a particular direction to a solution.
Jul 09 2009
Hello Tim,BCS wrote:Hello Tim,Anyway I like how you can get a slice of array that is just a view into the original. If I modify the slice, it modifies the full original array which can be very useful. If however I modify the length of the slice which I was doing in an attempt to extend the view, it becomes it's own array.
Was this a design choice, bug, undefined behavior, etc...?
char[] buff1 = something; char[] buff2 = buff1[10..20]; buff2 = buff2.ptr[0..20]; note this is unsafe and will give you no warnings if you extend past the end of buff1;
mean that I was just trying to extend the view.
If that doesn't "extend the view", then I'm not understanding what you are asking for. the above should compile to the sudocode: t = &(buff.ptr[0]); L = 20-0; buff2.{ptr, length} = {t, L}; and should optimize to just an assignment to length.Also depending on what news reader you use you should see that it branched off in a particular direction to a solution.
If you are referring the your response to Steven Schveighoffer, that amounts to the same thing I proposed but is even less safe (I don't think the layout of an array reference is speced) and harder to understand.
Jul 09 2009
Sorry I misread (lacking sleep). I can just re slice from the slice,
silly me.
import std.stdio;
void extendSlice(T)(ref T[] slice, uint extendCount)
{
slice = slice.ptr[0..slice.length+extendCount];
}
void main()
{
char[] a = "Hello".dup;
char[] b;
b = a[1..3]; //b is a view into a
writeln(a); //(Hello)
writeln(b); //(el)
extendSlice(b,1);
writeln(a); //(Hello)
writeln(b); //(ell)
}
Jul 09 2009
Hello Tim,Sorry I misread (lacking sleep).
Been there, done that. :oz
Jul 09 2009









Tim Matthews <tim.matthews7 gmail.com> 