digitalmars.D.learn - Static Constructors
- "Saaa" <empty needmail.com> Oct 03 2008
- BCS <ao pathlink.com> Oct 03 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- BCS <ao pathlink.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- "Jarrett Billingsley" <jarrett.billingsley gmail.com> Oct 03 2008
- BCS <ao pathlink.com> Oct 03 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- Gide Nwawudu <gide btinternet.com> Oct 05 2008
- Gide Nwawudu <gide btinternet.com> Oct 05 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- "Denis Koroskin" <2korden gmail.com> Oct 04 2008
- BCS <ao pathlink.com> Oct 04 2008
- "Denis Koroskin" <2korden gmail.com> Oct 04 2008
- "Denis Koroskin" <2korden gmail.com> Oct 04 2008
- "Denis Koroskin" <2korden gmail.com> Oct 05 2008
- "Jarrett Billingsley" <jarrett.billingsley gmail.com> Oct 05 2008
- "Jarrett Billingsley" <jarrett.billingsley gmail.com> Oct 05 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- "Steven Schveighoffer" <schveiguy yahoo.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- bearophile <bearophileHUGS lycos.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
- "Jarrett Billingsley" <jarrett.billingsley gmail.com> Oct 04 2008
- "Saaa" <empty needmail.com> Oct 04 2008
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( .. );
fruit[$-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
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( .. );
fruit[$-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;
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;
void reg(T b) { static int a = 0; data[a++] = b;
}
Oct 04 2008
Reply to Saaa,uint at = 0; if(extra <= at) data.length = (at+1)*2;
Yes, Oops, (darn remnants :-)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;
It's a variables declaration (with T being the type that is needed).void reg(T b) { static int a = 0; data[a++] = b;
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.}
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:deleting is even more annoying.
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;
Oct 03 2008
deleting is even more annoying.
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;
Yes, like that :) What is the difference between those two? I mean, what do you mean by in-place.
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...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 :)
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; -Steve
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; -Steve
Because 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: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.
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 -Steve
Oct 04 2008
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 -Steve
Rest 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 fail
I 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, 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...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 :)
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; -Steve
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] Gide
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: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?
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. Gide
Oct 05 2008
Have you heard of the append operator? fruit ~= new Fruit(...);
Yeah, but never used it other than with strings . . silly me.deleting is even more annoying.
You don't have to delete anything. This is what the GC is for.
I think I don't get GC use. How do I actually delete one of those fruits then?
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
On Sat, 04 Oct 2008 16:34:56 +0400, Saaa <empty needmail.com> wrote:deleting is even more annoying.
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;
Yes, like that :) What is the difference between those two? I mean, what do you mean by in-place.
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; }
Oct 04 2008
Reply to Denis,On Sat, 04 Oct 2008 16:34:56 +0400, Saaa <empty needmail.com> wrote:deleting is even more annoying.
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;
What is the difference between those two? I mean, what do you mean by in-place.
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; }
The added speed from array copy optimizations might overcome the cost of alocing. OTOH use memmove and you will do even better.
Oct 04 2008
On Sun, 05 Oct 2008 01:37:30 +0400, Saaa <empty needmail.com> wrote:for example: int[] data = [0,1,2,3,4].dup;
because [0,1,2,3,4] is readonlyint[] dataslice = data[0..2]; dataslice.length = 1; assert(data[1] == 1); // this would fail -Steve
Rest makes sense.
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...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 :)
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; -Steve
Great advice, thanks!
Oct 04 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:"Saaa" <empty needmail.com> wrote in message news:gc8314$24e0$1 digitalmars.com...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 :)
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; -Steve
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] Gide
Errr... And what is an expected output? I believe the actual output is correct.
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, 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: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?
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. Gide
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.
Oct 05 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
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
On Sat, Oct 4, 2008 at 2:22 PM, bearophile <bearophileHUGS lycos.com> wrote: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
Uh, ok, who cares what coding style you use?
Oct 04 2008









"Saaa" <empty needmail.com> 