digitalmars.D.learn - back to arays
- Max Samuha (11/11) May 15 2006 I thought array references are similar to object references like in C#
- Regan Heath (9/20) May 15 2006 The D philosophy is "copy on write". Whenever you have several reference...
- Derek Parnell (21/36) May 15 2006 I assume for some valid reason you want this behaviour...
- Tom S (16/48) May 15 2006 Nope, the earlier one :)
- Derek Parnell (28/66) May 15 2006 That's what you get while trying to rush out of the office, late again f...
- Bruno Medeiros (9/15) May 15 2006 I'll bet the identifiers are on the same scope just for simplification
- Max Samuha (5/23) May 15 2006 No, i certainly don't want to do this. I just expected from D's
- Chris Nicholson-Sauls (9/40) May 15 2006 I have made some similar mistakes before, to be sure. Essentially D's a...
- Bruno Medeiros (5/17) May 15 2006 You mean "to output '10 10'", no?
- Tom S (9/10) May 15 2006 Arrrgh you're right :S
- Oskar Linde (36/51) May 15 2006 The behavior of D's built in arrays have been the cause of much confusio...
- James Pelcis (3/18) May 15 2006 You can always "cheat" and do:
- Max Samuha (7/12) May 17 2006 If the garbage collector moves data referenced by p, i guess all
- Unknown W. Brackets (11/28) May 17 2006 I should note, currently, DMD's implementation won't move anything
- Derek Parnell (15/17) May 17 2006 Even if the length is increased beyond the size that has been allocated ...
- Bruno Medeiros (8/22) May 18 2006 Yes, that's what it does, but that resizing results from an explicit
- Unknown W. Brackets (12/30) May 19 2006 Right, sorry if I was unclear.
int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. Thanks
May 15 2006
On Mon, 15 May 2006 10:05:22 +0300, Max Samuha <maxter i.com.ua_spamless> wrote:int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. ThanksThe D philosophy is "copy on write". Whenever you have several references to the same data and you decide to write to the data, you should make a copy and write to the copy. If you want to constantly have several references to the same data then yes, you will have to update the references whenever you make change or write a class to handle that for you. Regan
May 15 2006
On Mon, 15 May 2006 10:05:22 +0300, Max Samuha wrote:int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. ThanksI assume for some valid reason you want this behaviour... int[] a = new int[20]; int[] b = a; int[] c = a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17 The simplest way to do this is ... int[] a = new int[20]; int[]* b = &a; int[]* c = &a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17 I'm not sure why one would need this behaviour though. Why do you need two identifiers in the same scope to reference the same data? -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 15/05/2006 5:49:08 PM
May 15 2006
Derek Parnell wrote:On Mon, 15 May 2006 10:05:22 +0300, Max Samuha wrote:But... it will display '17 17'.int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. ThanksI assume for some valid reason you want this behaviour... int[] a = new int[20]; int[] b = a; int[] c = a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17The simplest way to do this is ... int[] a = new int[20]; int[]* b = &a; int[]* c = &a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17Nope, the earlier one :) As I understand it, he'd like this code: to output '20 20'. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 15 2006
On Mon, 15 May 2006 20:24:39 +1000, Tom S <h3r3tic remove.mat.uni.torun.pl> wrote:Derek Parnell wrote:That's what you get while trying to rush out of the office, late again for dinner. You are right. Here is my improved attempt and what I was trying to say earlier... import std.stdio; void main() { int[] a; int[]* b; int[]* c; b = &a; c = &a; a.length= 40; a[0] = 17; writefln("%d %d", c.length, b.length); writefln("%d %d", *c[0], *b[0]); } ------------------------- This displays 40 40 17 17 ------------------------- But I still don't know why one would want to do this? -- Derek Parnell Melbourne, AustraliaOn Mon, 15 May 2006 10:05:22 +0300, Max Samuha wrote:But... it will display '17 17'.int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. ThanksI assume for some valid reason you want this behaviour... int[] a = new int[20]; int[] b = a; int[] c = a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17The simplest way to do this is ... int[] a = new int[20]; int[]* b = &a; int[]* c = &a; a[0] = 17; writefln("%s %s", b[0], c[0]); // Displays 17 17Nope, the earlier one :) As I understand it, he'd like this code: to output '20 20'.
May 15 2006
Derek Parnell wrote:I'm not sure why one would need this behaviour though. Why do you need two identifiers in the same scope to reference the same data?Derek Parnell wrote:But I still don't know why one would want to do this?I'll bet the identifiers are on the same scope just for simplification purposes. The case were you would want to have a dyn array to behave "wholly" like a reference type is quite common and necessary, just like associative arrays are now "wholly" a reference type. -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 15 2006
On Mon, 15 May 2006 23:08:26 +1000, "Derek Parnell" <derek psych.ward> wrote:void main() { int[] a; int[]* b; int[]* c; b = &a; c = &a; a.length= 40; a[0] = 17; writefln("%d %d", c.length, b.length); writefln("%d %d", *c[0], *b[0]); } ------------------------- This displays 40 40 17 17 ------------------------- But I still don't know why one would want to do this?No, i certainly don't want to do this. I just expected from D's dynamic arrays what was described here in a more readable English as arrays being reference types. That's clearer now. Thanks
May 15 2006
Max Samuha wrote:On Mon, 15 May 2006 23:08:26 +1000, "Derek Parnell" <derek psych.ward> wrote:I have made some similar mistakes before, to be sure. Essentially D's arrays are really structures, one of the fields of which being a pointer to the real data. Sometimes this means another array variable will be pointing to the same data, but this leaves you when you try to muck with the array. Although, in some (not all) cases you can get behavior like what you want by using inout parameters (or pointers), and in some other cases (still not all) you could probably use slice semantics. -- Chris Nicholson-Saulsvoid main() { int[] a; int[]* b; int[]* c; b = &a; c = &a; a.length= 40; a[0] = 17; writefln("%d %d", c.length, b.length); writefln("%d %d", *c[0], *b[0]); } ------------------------- This displays 40 40 17 17 ------------------------- But I still don't know why one would want to do this?No, i certainly don't want to do this. I just expected from D's dynamic arrays what was described here in a more readable English as arrays being reference types. That's clearer now. Thanks
May 15 2006
Tom S wrote:As I understand it, he'd like this code: to output '20 20'.You mean "to output '10 10'", no? -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 15 2006
Bruno Medeiros wrote:You mean "to output '10 10'", no?Arrrgh you're right :S -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d-pu s+: a-->----- C+++$>++++ UL P+ L+ E--- W++ N++ o? K? w++ !O !M V? PS- PE- Y PGP t 5 X? R tv-- b DI- D+ G e>+++ h>++ !r !y ------END GEEK CODE BLOCK------ Tomasz Stachowiak /+ a.k.a. h3r3tic +/
May 15 2006
Max Samuha skrev:int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. ThanksThe behavior of D's built in arrays have been the cause of much confusion. D's arrays actually have a kind of schizophrenic nature. They are value types referring to some portion of memory, and as such, they are not pure arrays (of course a matter of interpretation), but rather array slices. On the other hand they support append operations, and automatically copy and reallocate the data when the length is increased, which doesn't make sense for a pure slice type. So in the sense of being arrays, D's arrays neither fulfill the expected semantics of being a value type nor a reference type. This will probably make many D users cringe, by my suggestion is to use an array wrapper type with reference semantics. Something like this: (untested and incomplete code) class Array(T) { T[] data; this() {} this(int n) { length(n); } this(T[] data) { this.data = data; } void length(size_t n) { data.length = n; } size_t length() { return data.length; } Array dup() { return new Array(data.dup); } T opIndex(size_t i) { return data[i]; } T opIndexAssign(T v, size_t i) { return data[i] = v; } T[] opSlice(size_t a, size_t b) { return data[a..b]; } int opApply(...) {...} } Usage: Array!(int) a = new Array!(int)(20); Array!(int) b = a; a.length = 40; // a is NOT copied and b is updated to point to a's data Properly implemented this will work as you expect with one caveat. There is no reference return type for opIndex, making arrays of structs somewhat inconvenient. I think you can find a proper implementation in the ancient DTL library. Regards, Oskar
May 15 2006
You can always "cheat" and do: alias a b; Max Samuha wrote:int[] a = new int[20]; int[] b = a; a.length = 40; // a is copied and b is not updated to point to a's data; Does it mean that anytime i change an array, i have to manually update all references to it or should i wrap my array in an Array class so that all references to any instance of that array remain valid? If the question have been already discussed please refer me to the right thread. Thanks
May 15 2006
There's one more question about arrays. From D specs:A pointer to the start of a garbage collected object need not be maintained if a pointer to the interior of the object exists. char[] p = new char[10]; char[] q = p[3..6]; // q is enough to hold on to the object, don't need to keep // p as well.If the garbage collector moves data referenced by p, i guess all pointers to slices of p will be updated correctly. What if i set p to null or p goes out of scope and q is still reachable, will the memory (before q.ptr and after q.ptr + q.length - 1) that was pointed to by p be reclaimed by the garbage collector?
May 17 2006
I should note, currently, DMD's implementation won't move anything you're pointing to. And... as you probably know, memory is allocated in chunks from the operating system. Without making a copy, you can't deallocate just one part. So DMD won't currently. However, if the memory were to be copied I'd expect it to be perfectly reasonable that the GC might not keep the old array data (although that would certainly be non-trivial for the GC to do.) I wouldn't depend on it - and it seems brittle anyway, even if it were guaranteed. -[Unknown]There's one more question about arrays. From D specs:A pointer to the start of a garbage collected object need not be maintained if a pointer to the interior of the object exists. char[] p = new char[10]; char[] q = p[3..6]; // q is enough to hold on to the object, don't need to keep // p as well.If the garbage collector moves data referenced by p, i guess all pointers to slices of p will be updated correctly. What if i set p to null or p goes out of scope and q is still reachable, will the memory (before q.ptr and after q.ptr + q.length - 1) that was pointed to by p be reclaimed by the garbage collector?
May 17 2006
On Wed, 17 May 2006 22:07:12 -0700, Unknown W. Brackets wrote:I should note, currently, DMD's implementation won't move anything you're pointing to.Even if the length is increased beyond the size that has been allocated for a dynamic array? I thought that DMD allocated a new block of the right size and copied data from the old block to it then released the old block back to the GC. I think that if the length is decreased then no copying goes on and that no memory is released back to the GC, but can be later reused if the length then is increased anywhere up to the original allocation size. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 18/05/2006 3:20:14 PM
May 17 2006
Derek Parnell wrote:On Wed, 17 May 2006 22:07:12 -0700, Unknown W. Brackets wrote:Yes, that's what it does, but that resizing results from an explicit programmer action, and not from the GC. When W. Brackets mentioned "DMD's implementation" I believe he meant the GC only, which, as is known, indeed doesn't currently move anything.I should note, currently, DMD's implementation won't move anything you're pointing to.Even if the length is increased beyond the size that has been allocated for a dynamic array? I thought that DMD allocated a new block of the right size and copied data from the old block to it then released the old block back to the GC.I think that if the length is decreased then no copying goes on and that no memory is released back to the GC, but can be later reused if the length then is increased anywhere up to the original allocation size.-- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 18 2006
Right, sorry if I was unclear. When you resize an array, it makes a copy - it still doesn't move anything. When I was talking about moving, I was meaning a compacting (defragmenting) garbage collector. DMD's garbage collector holds onto any pointer references which are still active, even if you change the length of a dynamic array - so that issue shouldn't affect this. For slices to work properly, the above must be guaranteed afaik. But holding onto the memory around said slices need not be guaranteed. PS: I've been called a lot of different things (Uncle Brackets, Big U, etc.), but I hadn't ever heard "W. Brackets". Heh. -[Unknown]Derek Parnell wrote:On Wed, 17 May 2006 22:07:12 -0700, Unknown W. Brackets wrote:Yes, that's what it does, but that resizing results from an explicit programmer action, and not from the GC. When W. Brackets mentioned "DMD's implementation" I believe he meant the GC only, which, as is known, indeed doesn't currently move anything.I should note, currently, DMD's implementation won't move anything you're pointing to.Even if the length is increased beyond the size that has been allocated for a dynamic array? I thought that DMD allocated a new block of the right size and copied data from the old block to it then released the old block back to the GC.
May 19 2006