digitalmars.D.learn - Static Constructors
- Saaa (18/18) Oct 03 2008 I've been using classes for a few months now and I keep on making arrays...
- BCS (22/46) Oct 03 2008 Sort of: switch "void init" for "static this" and you won't need to call...
- Saaa (5/50) Oct 04 2008 Initially I'd be adding a lot, but after that only sparsely.
- Jarrett Billingsley (5/23) Oct 03 2008 Have you heard of the append operator?
- BCS (7/13) Oct 03 2008 delete could be "remove element 42 from an array of 54 resulting an an a...
- Saaa (3/14) Oct 04 2008 Yes, like that :)
- Denis Koroskin (9/26) Oct 04 2008 First one allocates new memory block.
- Saaa (1/9) Oct 04 2008 Yay, thats how I do it :)
- Steven Schveighoffer (9/20) Oct 04 2008 If you want the memory removed as soon as possible, you should zero out ...
- Saaa (3/11) Oct 04 2008 Because the GC sees all allocated memory as used and an array doesn't
- bearophile (22/28) Oct 04 2008 Really?? Is that another bug of dynamic arrays? I have assumed that dyna...
- Steven Schveighoffer (16/46) Oct 04 2008 Setting data.length to one less is equivalent to:
- Saaa (2/8) Oct 04 2008 Rest makes sense.
- Denis Koroskin (2/14) Oct 04 2008
- bearophile (6/10) Oct 04 2008 I see, the current light semantics of slices require the extra data to b...
- Denis Koroskin (3/26) Oct 04 2008 Great advice, thanks!
- Gide Nwawudu (11/33) Oct 05 2008 The following code outputs [0 4 2 3], is this a bug in D2?
- Denis Koroskin (4/43) Oct 05 2008 Errr... And what is an expected output?
- Jarrett Billingsley (6/14) Oct 05 2008 now data is [0 4 2 3 0]
- Gide Nwawudu (6/21) Oct 05 2008 My main issue was with eraseNth re-ordering elements, but if moving
- Jarrett Billingsley (8/38) Oct 05 2008 It's the faster method is all. If you want a stable remove, you can
- BCS (3/27) Oct 04 2008 The added speed from array copy optimizations might overcome the cost of...
- Saaa (3/8) Oct 04 2008 I think I don't get GC use. How do I actually delete one of those fruits...
- bearophile (7/9) Oct 04 2008 The GC deletes an object (usually, but sometimes it doesn't do it becaus...
- Saaa (1/15) Oct 04 2008
- bearophile (5/6) Oct 04 2008 No, deleting them manually is un-D-tonic :-)
- Saaa (23/23) Oct 04 2008 Can I do something like this, or should I use the static constructor for...
- Steven Schveighoffer (14/37) Oct 04 2008 typo, and you are using C-style array syntax (which works, but is
- bearophile (9/13) Oct 04 2008 Note that often this is enough:
- Jarrett Billingsley (2/15) Oct 04 2008 Uh, ok, who cares what coding style you use?
- bearophile (6/7) Oct 04 2008 Python and Ruby teach that in a language a more uniform coding style hel...
- Saaa (20/20) Oct 04 2008 What would happen here?
- Saaa (2/2) Oct 04 2008 Thanks!
I've been using classes for a few months now and I keep on making arrays of instances like: class Fruit { this( parameters ) { } .. } Fruits fruit[]; void init() { fruit.length=fruit.length+1; // annoys me :) fruit[$]=new Fruit( .. ); } deleting is even more annoying. Now I've been reading about static constructors and is that somehow a solution to this manual array management?
Oct 03 2008
Reply to Saaa,I've been using classes for a few months now and I keep on making arrays of instances like: class Fruit { this( parameters ) { } .. } Fruits fruit[]; void init() { fruit.length=fruit.length+1; // annoys me :) fruit[$]=new Fruit( .. ); } deleting is even more annoying. Now I've been reading about static constructors and is that somehow a solution to this manual array management?Sort of: switch "void init" for "static this" and you won't need to call init from main, but that's about all you will get. Also you can not control the order of execution. 2 minor nits:fruit[$]=new Fruit( .. );should befruit[$-1]=new Fruit( .. );typo? If you are going to be adding more than very few items to the array, pick a better allocation scheme uint at = 0; if(extra <= at) data.length = (at+1)*2; data[at] = t; at++; //when done adding data.length = at; another option would be to use an AA if order isn't relevant. T[int] data; void reg(T b) { static int a = 0; data[a++] = b; }
Oct 03 2008
yeah :), originally I did fruit[].length-1.I've been using classes for a few months now and I keep on making arrays of instances like: class Fruit { this( parameters ) { } .. } Fruits fruit[]; void init() { fruit.length=fruit.length+1; // annoys me :) fruit[$]=new Fruit( .. ); } deleting is even more annoying. Now I've been reading about static constructors and is that somehow a solution to this manual array management?Sort of: switch "void init" for "static this" and you won't need to call init from main, but that's about all you will get. Also you can not control the order of execution. 2 minor nits:fruit[$]=new Fruit( .. );should befruit[$-1]=new Fruit( .. );typo?If you are going to be adding more than very few items to the array, pick a better allocation scheme uint at = 0; if(extra <= at) data.length = (at+1)*2;extra=data.length; ?data[at] = t; at++; //when done adding data.length = at;Initially I'd be adding a lot, but after that only sparsely.another option would be to use an AA if order isn't relevant. T[int] data;Is this code? I mean should there be an int or 'int'?void reg(T b) { static int a = 0; data[a++] = b;How does this work when it's no dynamic array?}
Oct 04 2008
Reply to Saaa,Yes, Oops, (darn remnants :-)uint at = 0; if(extra <= at) data.length = (at+1)*2;extra=data.length; ?It's a variables declaration (with T being the type that is needed).data[at] = t; at++; //when done adding data.length = at;Initially I'd be adding a lot, but after that only sparsely.another option would be to use an AA if order isn't relevant. T[int] data;Is this code? I mean should there be an int or 'int'?http://www.digitalmars.com/d/1.0/arrays.html#associative It's a hash table, the key is "a". It's incremented so that you get a unique value for each insertion. ("data[rand()] = b;" might work also) you can also flip it the other way int[T] data; ... data[b] = 0; to access the data: data.keys.void reg(T b) { static int a = 0; data[a++] = b;How does this work when it's no dynamic array?}
Oct 04 2008
On Fri, Oct 3, 2008 at 5:57 PM, Saaa <empty needmail.com> wrote:I've been using classes for a few months now and I keep on making arrays of instances like: class Fruit { this( parameters ) { } .. } Fruits fruit[]; void init() { fruit.length=fruit.length+1; // annoys me :) fruit[$]=new Fruit( .. ); }Have you heard of the append operator? fruit ~= new Fruit(...);deleting is even more annoying.You don't have to delete anything. This is what the GC is for.Now I've been reading about static constructors and is that somehow a solution to this manual array management?I don't know what you're trying to do, so it may or may not be a solution.
Oct 03 2008
Reply to Jarrett,On Fri, Oct 3, 2008 at 5:57 PM, Saaa <empty needmail.com> wrote:delete could be "remove element 42 from an array of 54 resulting an an array of 53" data = data[0..42] ~ data[43..$]; or data[42..$-1] = data[43..$].dup; // in-place sortof data.length = data.length-1;deleting is even more annoying.You don't have to delete anything. This is what the GC is for.
Oct 03 2008
Yes, like that :) What is the difference between those two? I mean, what do you mean by in-place.delete could be "remove element 42 from an array of 54 resulting an an array of 53" data = data[0..42] ~ data[43..$]; or data[42..$-1] = data[43..$].dup; // in-place sortof data.length = data.length-1;deleting is even more annoying.You don't have to delete anything. This is what the GC is for.
Oct 04 2008
On Sat, 04 Oct 2008 16:34:56 +0400, Saaa <empty needmail.com> wrote:First one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yes, like that :) What is the difference between those two? I mean, what do you mean by in-place.delete could be "remove element 42 from an array of 54 resulting an an array of 53" data = data[0..42] ~ data[43..$]; or data[42..$-1] = data[43..$].dup; // in-place sortof data.length = data.length-1;deleting is even more annoying.You don't have to delete anything. This is what the GC is for.
Oct 04 2008
First one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yay, thats how I do it :)
Oct 04 2008
"Saaa" <empty needmail.com> wrote in message news:gc8314$24e0$1 digitalmars.com...If you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1; -SteveFirst one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yay, thats how I do it :)
Oct 04 2008
If you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1; -SteveBecause the GC sees all allocated memory as used and an array doesn't deallocate memory when made smaller? Or just delete it :)
Oct 04 2008
Steven Schveighoffer:If you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1;Really?? Is that another bug of dynamic arrays? I have assumed that dynamic arrays do such things automatically. I do that in my collections, for example: ... void length(int newlen) { if (newlen < 0 || newlen > this._length) throw new ArgumentException("ArrayBuilder.length(newlen):" " newlen < 0 || newlen > ArrayBuilder.length"); static if (IsReferenceType!(T)) { static if (IsStaticArray!(T)) { T Tinit; this.data[newlen .. this._length][] = Tinit; } else { this.data[newlen .. this._length] = T.init; } } this._length = newlen; } ... If what you say is true, then it deserves a space on bugzilla and to be fixed soon. Bye, bearophile
Oct 04 2008
"bearophile" wroteSteven Schveighoffer:Setting data.length to one less is equivalent to: data = data[0..$-1]; Which effectively leaves the pointer to the class untouched in the unused portion of the memory. However, the memory is still valid in terms of the GC. The GC scans the entire block for pointers, even if you aren't using all of the block. That is why it always zeros out memory before giving it to you. If setting the length to less than the original value did something special like zero out the now unused elements, then weird things would happen. for example: int[] data = [0,1,2,3,4].dup; int[] dataslice = data[0..2]; dataslice.length = 1; assert(data[1] == 1); // this would fail -SteveIf you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1;Really?? Is that another bug of dynamic arrays? I have assumed that dynamic arrays do such things automatically. I do that in my collections, for example: ... void length(int newlen) { if (newlen < 0 || newlen > this._length) throw new ArgumentException("ArrayBuilder.length(newlen):" " newlen < 0 || newlen > ArrayBuilder.length"); static if (IsReferenceType!(T)) { static if (IsStaticArray!(T)) { T Tinit; this.data[newlen .. this._length][] = Tinit; } else { this.data[newlen .. this._length] = T.init; } } this._length = newlen; } ... If what you say is true, then it deserves a space on bugzilla and to be fixed soon.
Oct 04 2008
for example: int[] data = [0,1,2,3,4].dup;why the dup?int[] dataslice = data[0..2]; dataslice.length = 1; assert(data[1] == 1); // this would fail -SteveRest makes sense.
Oct 04 2008
On Sun, 05 Oct 2008 01:37:30 +0400, Saaa <empty needmail.com> wrote:because [0,1,2,3,4] is readonlyfor example: int[] data = [0,1,2,3,4].dup;why the dup?int[] dataslice = data[0..2]; dataslice.length = 1; assert(data[1] == 1); // this would fail -SteveRest makes sense.
Oct 04 2008
Steven Schveighoffer:int[] data = [0,1,2,3,4].dup; int[] dataslice = data[0..2]; dataslice.length = 1; assert(data[1] == 1); // this would failI see, the current light semantics of slices require the extra data to be kept. You are right, and I am glad to be wrong :-) (That collection I have shown can't be sliced, but in special situations that problem may be present. I'll have to think about it). Thank you for your answers, bye, bearophile
Oct 04 2008
On Sat, 04 Oct 2008 22:02:43 +0400, Steven Schveighoffer <schveiguy yahoo.com> wrote:"Saaa" <empty needmail.com> wrote in message news:gc8314$24e0$1 digitalmars.com...Great advice, thanks!If you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1; -SteveFirst one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yay, thats how I do it :)
Oct 04 2008
On Sat, 4 Oct 2008 14:02:43 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> wrote:"Saaa" <empty needmail.com> wrote in message news:gc8314$24e0$1 digitalmars.com...The following code outputs [0 4 2 3], is this a bug in D2? int n = 1; int[] data = [0,1,2,3,4].dup; writeln(data); // [0 1 2 3 4] data[n] = data[$-1]; data[$-1] = 0; data.length = data.length - 1; writeln(data); // [0 4 2 3] GideIf you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1; -SteveFirst one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yay, thats how I do it :)
Oct 05 2008
On Sun, 05 Oct 2008 21:26:58 +0400, Gide Nwawudu <gide btinternet.com> wrote:On Sat, 4 Oct 2008 14:02:43 -0400, "Steven Schveighoffer" <schveiguy yahoo.com> wrote:Errr... And what is an expected output? I believe the actual output is correct."Saaa" <empty needmail.com> wrote in message news:gc8314$24e0$1 digitalmars.com...The following code outputs [0 4 2 3], is this a bug in D2? int n = 1; int[] data = [0,1,2,3,4].dup; writeln(data); // [0 1 2 3 4] data[n] = data[$-1]; data[$-1] = 0; data.length = data.length - 1; writeln(data); // [0 4 2 3] GideIf you want the memory removed as soon as possible, you should zero out the last element, otherwise, the GC will still think the element is being pointed to: data[n] = data[$-1]; data[$-1] = null; data.length = data.length - 1; -SteveFirst one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yay, thats how I do it :)
Oct 05 2008
On Sun, Oct 5, 2008 at 1:26 PM, Gide Nwawudu <gide btinternet.com> wrote:The following code outputs [0 4 2 3], is this a bug in D2? int n = 1; int[] data = [0,1,2,3,4].dup; writeln(data); // [0 1 2 3 4] data[n] = data[$-1];now data is [0 4 2 3 4]data[$-1] = 0;now data is [0 4 2 3 0]data.length = data.length - 1;now data is [0 4 2 3]writeln(data); // [0 4 2 3]And that's right. What's the issue?
Oct 05 2008
On Sun, 5 Oct 2008 15:31:38 -0400, "Jarrett Billingsley" <jarrett.billingsley gmail.com> wrote:On Sun, Oct 5, 2008 at 1:26 PM, Gide Nwawudu <gide btinternet.com> wrote:My main issue was with eraseNth re-ordering elements, but if moving the end element over the nth is standard, then I suppose it's ok. I would have expected a 'stable' version, i.e. [0 2 3 4] as the result. GideThe following code outputs [0 4 2 3], is this a bug in D2? int n = 1; int[] data = [0,1,2,3,4].dup; writeln(data); // [0 1 2 3 4] data[n] = data[$-1];now data is [0 4 2 3 4]data[$-1] = 0;now data is [0 4 2 3 0]data.length = data.length - 1;now data is [0 4 2 3]writeln(data); // [0 4 2 3]And that's right. What's the issue?
Oct 05 2008
On Sun, Oct 5, 2008 at 5:32 PM, Gide Nwawudu <gide btinternet.com> wrote:On Sun, 5 Oct 2008 15:31:38 -0400, "Jarrett Billingsley" <jarrett.billingsley gmail.com> wrote:It's the faster method is all. If you want a stable remove, you can either copy everything after the removed element down a slot, or you can create a new array with "a[0 .. n] ~ a[n + 1 .. $]". The former requires less memory and less strain on the GC, and unless you have a really fancy compiler that will autoparallelize the copy from the old array into the new, the second solution will be no faster at copying the data.On Sun, Oct 5, 2008 at 1:26 PM, Gide Nwawudu <gide btinternet.com> wrote:My main issue was with eraseNth re-ordering elements, but if moving the end element over the nth is standard, then I suppose it's ok. I would have expected a 'stable' version, i.e. [0 2 3 4] as the result. GideThe following code outputs [0 4 2 3], is this a bug in D2? int n = 1; int[] data = [0,1,2,3,4].dup; writeln(data); // [0 1 2 3 4] data[n] = data[$-1];now data is [0 4 2 3 4]data[$-1] = 0;now data is [0 4 2 3 0]data.length = data.length - 1;now data is [0 4 2 3]writeln(data); // [0 4 2 3]And that's right. What's the issue?
Oct 05 2008
Reply to Denis,On Sat, 04 Oct 2008 16:34:56 +0400, Saaa <empty needmail.com> wrote:The added speed from array copy optimizations might overcome the cost of alocing. OTOH use memmove and you will do even better.First one allocates new memory block. Second one attempts to erase an element in-place. Dupping, however, allocates new memory, too. The best solution would be as follows: void eraseNth(ref T[] data, int n) { data[n] = data[$-1]; data.length = data.length - 1; }Yes, like that :) What is the difference between those two? I mean, what do you mean by in-place.delete could be "remove element 42 from an array of 54 resulting an an array of 53" data = data[0..42] ~ data[43..$]; or data[42..$-1] = data[43..$].dup; // in-place sortof data.length = data.length-1;deleting is even more annoying.You don't have to delete anything. This is what the GC is for.
Oct 04 2008
Have you heard of the append operator? fruit ~= new Fruit(...);Yeah, but never used it other than with strings . . silly me.I think I don't get GC use. How do I actually delete one of those fruits then?deleting is even more annoying.You don't have to delete anything. This is what the GC is for.
Oct 04 2008
Saaa:I think I don't get GC use. How do I actually delete one of those fruits then?The GC deletes an object (usually, but sometimes it doesn't do it because it's not a precise GC) when there are no references to/from it. So if you keep it just inside an array, and it has no inbound references, and you remove it somehow (for example overwriting it with the last item of the array and then reducing the length of the array by 1), the GC loses the only reference to that objects, and deallocates it. Note the same thing happens in most languages/systems that have a GC. If your object manages some other resources beside its memory, for example an open file, you have to close it inside the destructor of your object. If the not precise GC keeps a spurious (wrong) reference to your object (because somewhere an int value looks like a pointer to the object memory block), then you are in troubles... Bye, bearophile
Oct 04 2008
Thanks, from this I'd rather delete them manually :)The GC deletes an object (usually, but sometimes it doesn't do it because it's not a precise GC) when there are no references to/from it. So if you keep it just inside an array, and it has no inbound references, and you remove it somehow (for example overwriting it with the last item of the array and then reducing the length of the array by 1), the GC loses the only reference to that objects, and deallocates it. Note the same thing happens in most languages/systems that have a GC. If your object manages some other resources beside its memory, for example an open file, you have to close it inside the destructor of your object. If the not precise GC keeps a spurious (wrong) reference to your object (because somewhere an int value looks like a pointer to the object memory block), then you are in troubles... Bye, bearophile
Oct 04 2008
Saaa Wrote:Thanks, from this I'd rather delete them manually :)No, deleting them manually is un-D-tonic :-) In most situations you let the GC do its work. Bye, bearophile
Oct 04 2008
Can I do something like this, or should I use the static constructor for this? If so, how should I set the first parameter:size ? Fruits fruit[]; class Fruit { this( parameters ) { fruit[].length=fruit[].length+1; fruit[$-1]=this; } .. void stuff() { } .. } new fruit( .. ); new fruit( .. ); foreach (Fruit f; fruit) { f.stuff(); }
Oct 04 2008
"Saaa" wroteCan I do something like this, or should I use the static constructor for this? If so, how should I set the first parameter:size ? Fruits fruit[];typo, and you are using C-style array syntax (which works, but is discouraged). This should be: Fruit[] fruit; Means, 'I declare an array of Fruit called fruit'class Fruit { this( parameters ) { fruit[].length=fruit[].length+1; fruit[$-1]=this;Don't do the [] operator, I think this may create a temporary array struct, and would not affect the global variable at all: fruit.length = fruit.length + 1; But instead of this, it's probably better to write: fruit ~= this; Which does all that work for you :)} .. void stuff() { } .. } new fruit( .. ); new fruit( .. ); foreach (Fruit f; fruit) { f.stuff(); }This should work, but be aware that it's not thread safe if you are using multiple threads. -Steve
Oct 04 2008
Saaa:foreach (Fruit f; fruit) { f.stuff(); }Note that often this is enough: foreach (f; fruit) f.stuff; But I generally put the parentheses: foreach (f; fruit) f.stuff(); Bye, bearophile
Oct 04 2008
On Sat, Oct 4, 2008 at 2:22 PM, bearophile <bearophileHUGS lycos.com> wrote:Saaa:Uh, ok, who cares what coding style you use?foreach (Fruit f; fruit) { f.stuff(); }Note that often this is enough: foreach (f; fruit) f.stuff; But I generally put the parentheses: foreach (f; fruit) f.stuff(); Bye, bearophile
Oct 04 2008
Jarrett Billingsley:Uh, ok, who cares what coding style you use?Python and Ruby teach that in a language a more uniform coding style helps people understand each other code faster (and similar things), and that leads to more modules done. And nowadays already done modules that you can find on the net make a language successful instead of an ignored one. I know that the usual culture of C/C++ may be a little against such "freedoms", so I presume a significant part of the D community may not appreciate that. That also shows a disadvantage of Lisp-style macros, because having lot of customizations makes code less easy to understand by other people. And the OP may be unaware of some of the syntactic peculiarities of D, so it's useful to show them. Bye, bearophile
Oct 04 2008
What would happen here? Would the GC delete the newly made instances as there is no reference to it? Fruits fruit[]; class Fruit { this( parameters ) { } .. void stuff() { } .. } new fruit( .. ); //or can this only be called if there is an static constructor? new fruit( .. ); foreach (f; fruit) f.stuff(); //fruit is empty.
Oct 04 2008