www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - data containers

reply Moritz <mpipahl gspgmbh.com> writes:
Hello,

Im currently working on a gui framework for my game, and Im trying to 
find a versatile way to build my screens.

I thought about a generic "Screen" class, which has functions like 
"add_element()" to insert a sprite or text into a layer on the screen.

Rendering is then done from the lowest layer to the highest one.
My question is now how I can implement these Layers, since I didnt find 
LikedLists or Hastables in Phobos.

My Idea in C++ would be to have a hashtable int to linked list, which 
gives me the linked list for a layer upon inserting the layer number, 
and the linked list then contains my ScreenObjects (a base class for 
images, text, buttons and so on).
What would be the best way to do this in D?
Jul 02 2008
next sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Thu, 03 Jul 2008 01:04:09 +0400, Moritz <mpipahl gspgmbh.com> wrote:

 Hello,

 Im currently working on a gui framework for my game, and Im trying to  
 find a versatile way to build my screens.

 I thought about a generic "Screen" class, which has functions like  
 "add_element()" to insert a sprite or text into a layer on the screen.

 Rendering is then done from the lowest layer to the highest one.
 My question is now how I can implement these Layers, since I didnt find  
 LikedLists or Hastables in Phobos.

 My Idea in C++ would be to have a hashtable int to linked list, which  
 gives me the linked list for a layer upon inserting the layer number,  
 and the linked list then contains my ScreenObjects (a base class for  
 images, text, buttons and so on).
 What would be the best way to do this in D?

I like the way it is done in a PopCap Framework (available for free from developer.popcap.com; Zuma, Peggle, and all the others PopCap games are made with this framework). Everything is a Widget. Widgets can be built into a hierarchically, one nested in another. Child widgets are stored in a linked list (for easy appending and removal during iteration over collection) in an order they are added. This is the same order they are drawn to screen (topmost widget is at the end and drawn last). There are two main phases: Update and Drawing. During update, all widgets' Update() method is called recursively starting from the root of the hierarchy. The same goes for a Drawing. Every widget defines a void Draw(Graphics g); method. All the drawing is done in this method. For example, you may have one big Screen class and do the rendering in a single method. Or, prefferred, have one lots of small widgets on a board, each of them draws itself only. There may be some ImageWidget (constructed from an image and renders static image), AnimatedWidget (constructed from a frame sequence), etc. Fonts are not widgets, but are drawn as a part of some widget. For example, a button with a caption is a single object. Caption is drawn during a button.draw(g) call. Updates and Drawings are transparent to user. User just defines a new class, overrides its draw method and put newly constructed object to a board. That's it! Changing a widget order on the screen is as simple as moving an object inside a list: class Widget { ... void bringToFront(Widget child) { widgets.erase(child); widgets.pushBack(child); } ... } That's it. Hope this info will help you make your design desicions. P.S. Take a look into ArcLib, too: http://www.dsource.org/projects/arclib
Jul 02 2008
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Moritz" <mpipahl gspgmbh.com> wrote in message 
news:g4gqge$27fi$1 digitalmars.com...
 Hello,

 Im currently working on a gui framework for my game, and Im trying to find 
 a versatile way to build my screens.

 I thought about a generic "Screen" class, which has functions like 
 "add_element()" to insert a sprite or text into a layer on the screen.

 Rendering is then done from the lowest layer to the highest one.
 My question is now how I can implement these Layers, since I didnt find 
 LikedLists or Hastables in Phobos.

 My Idea in C++ would be to have a hashtable int to linked list, which 
 gives me the linked list for a layer upon inserting the layer number, and 
 the linked list then contains my ScreenObjects (a base class for images, 
 text, buttons and so on).
 What would be the best way to do this in D?

Well, hashtables are built into the language, though they are not necessarily the most performant implementation. List[int] table; Phobos doesn't have any built-in data structures, like hashtables or linked lists. Tango does. How necessary they are, I don't know, I've never actually used them. Most of the stuff I need to get done, I can get done with dynamic arrays and associative arrays. And really, if you can't type up a linked list in about 30 seconds, .. well, good luck to you.
Jul 02 2008
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Moritz" wrote
 Hello,

 Im currently working on a gui framework for my game, and Im trying to find 
 a versatile way to build my screens.

 I thought about a generic "Screen" class, which has functions like 
 "add_element()" to insert a sprite or text into a layer on the screen.

 Rendering is then done from the lowest layer to the highest one.
 My question is now how I can implement these Layers, since I didnt find 
 LikedLists or Hastables in Phobos.

 My Idea in C++ would be to have a hashtable int to linked list, which 
 gives me the linked list for a layer upon inserting the layer number, and 
 the linked list then contains my ScreenObjects (a base class for images, 
 text, buttons and so on).
 What would be the best way to do this in D?

I'm not a game programmer, but I did make a collections project for D that should support Phobos: www.dsource.org/projects/dcollections If you use it, let me know how it works for you. -Steve
Jul 03 2008
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Moritz wrote:

 Hello,
 
 Im currently working on a gui framework for my game, and Im trying to
 find a versatile way to build my screens.
 
 I thought about a generic "Screen" class, which has functions like
 "add_element()" to insert a sprite or text into a layer on the screen.
 
 Rendering is then done from the lowest layer to the highest one.
 My question is now how I can implement these Layers, since I didnt find
 LikedLists or Hastables in Phobos.

Maybe a reason to consider Tango? -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jul 03 2008
prev sibling next sibling parent reply Moritz <mpipahl gspgmbh.com> writes:
Thx for all your replies, but I hoped for a hint on how to implement it, 
since Im new to D.

 Lars Igesund: I considered Tango, but I had some issues with derelict, 
so I stopped the installation and decided to give phobos a closer look. 
But I bought the tango book, and will surely try tango out after I got 
some of my game ported and running in D.

 Steven: Ill try to use arrays first (for the sake of simplicity and to 
understand a bit more about D), and Ill try your collection afterwards 
(supplying the missing data containers in a project is surely a great 
idea, thank you!)

And pls forgive me if Im asking silly questions, but thats what 
beginners usually do :-)

Moritz schrieb:
 Hello,
 
 Im currently working on a gui framework for my game, and Im trying to 
 find a versatile way to build my screens.
 
 I thought about a generic "Screen" class, which has functions like 
 "add_element()" to insert a sprite or text into a layer on the screen.
 
 Rendering is then done from the lowest layer to the highest one.
 My question is now how I can implement these Layers, since I didnt find 
 LikedLists or Hastables in Phobos.
 
 My Idea in C++ would be to have a hashtable int to linked list, which 
 gives me the linked list for a layer upon inserting the layer number, 
 and the linked list then contains my ScreenObjects (a base class for 
 images, text, buttons and so on).
 What would be the best way to do this in D?

Jul 03 2008
parent reply Mike Parker <aldacron gmail.com> writes:
Moritz wrote:
 
  Lars Igesund: I considered Tango, but I had some issues with derelict, 
 so I stopped the installation and decided to give phobos a closer look. 
 

What issues did you have with Derelict? It works with Tango just fine.
Jul 03 2008
parent reply Moritz <mpipahl gspgmbh.com> writes:
Nothing all too serious, but I switched to tango and Derelict then didnt 
compile, becaue in endian.d there is an import:

private import std.intrinsic;

which is phobos, isnt it? So I kept phobos for the moment.

Mike Parker schrieb:
 Moritz wrote:
  Lars Igesund: I considered Tango, but I had some issues with 
 derelict, so I stopped the installation and decided to give phobos a 
 closer look.

What issues did you have with Derelict? It works with Tango just fine.

Jul 03 2008
parent Lars Ivar Igesund <larsivar igesund.net> writes:
Moritz wrote:

 Nothing all too serious, but I switched to tango and Derelict then didnt
 compile, becaue in endian.d there is an import:
 
 private import std.intrinsic;
 
 which is phobos, isnt it? So I kept phobos for the moment.

the name std.intrinsic is decided by the compiler, and so is used for both Tango and Phobos. -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Jul 04 2008
prev sibling next sibling parent reply Moritz <mpipahl gspgmbh.com> writes:
Another (more practical) question:

Im trying to use a two dimensional array for my ScreenElements:

ScreenElement[][] layer_map;

Then, Id like to itereate over all the ScreenElements in this array, but 
I get syntax errors in the inner foreach-loop, on the single_layer 
identifier.

Errormessage: Syntax error on token "single_layer", ; expected after 
this token

foreach(ScreenElement[] single_layer; layer_map[][])
{
	foreach(ScreenElement element, single_layer)
	{
		element.display();
	}
}

Can anyone tell me how to do this correctly?
Jul 03 2008
parent reply "Koroskin Denis" <2korden gmail.com> writes:
On Thu, 03 Jul 2008 21:56:17 +0400, Moritz <mpipahl gspgmbh.com> wrote:

 Another (more practical) question:

 Im trying to use a two dimensional array for my ScreenElements:

 ScreenElement[][] layer_map;

 Then, Id like to itereate over all the ScreenElements in this array, but  
 I get syntax errors in the inner foreach-loop, on the single_layer  
 identifier.

 Errormessage: Syntax error on token "single_layer", ; expected after  
 this token

 foreach(ScreenElement[] single_layer; layer_map[][])
 {
 	foreach(ScreenElement element, single_layer)
 	{
 		element.display();
 	}
 }

 Can anyone tell me how to do this correctly?

Works fine for me: ScreenElement[][] layer_map; foreach(ScreenElement[] single_layer; layer_map) // you may drop [][] as they are not needed { foreach(ScreenElement element; single_layer) // did you have had a typo here? , -> ; { element.display(); } }
Jul 03 2008
parent Moritz <mpipahl gspgmbh.com> writes:
Thank you, the error was:

"," instead of ";" in foreach(ScreenElement element; single_layer)
Jul 03 2008
prev sibling parent reply Moritz <mpipahl gspgmbh.com> writes:
So now I have a two dimensional array ready for my classes, but sadly, I 
cant find any information on how classes can be stored in a 
multidimensional array and how I can use the instances stored there.

Ive just guessed and typed:

int add_element(ScreenElement new_element, uint layer)
{
	if(layer <= layer_count)
	{
		ScreenElement[] single_layer = layer_map[layer];
		single_layer ~= new_element;
	}
	else
	{
		writefln("cant insert ScreenElement into non existing layer");
	}
	return 0;
}

Sadly, this doesnt work, I get an Error: ArrayBoundsError upon inserting.
Can anyone tell me how this is done, and maybe even where I can find 
usful examples for more cmplex uses of arrays in D?

My biggest problem ATM is the lack of good tutorials or examples, it 
seems that D is no easy language to get started with, once you want to 
do more than basics :-(
Jul 03 2008
next sibling parent reply torhu <no spam.invalid> writes:
Moritz wrote:
 So now I have a two dimensional array ready for my classes, but sadly, I 
 cant find any information on how classes can be stored in a 
 multidimensional array and how I can use the instances stored there.
 
 Ive just guessed and typed:
 
 int add_element(ScreenElement new_element, uint layer)
 {
 	if(layer <= layer_count)
 	{
 		ScreenElement[] single_layer = layer_map[layer];
 		single_layer ~= new_element;
 	}
 	else
 	{
 		writefln("cant insert ScreenElement into non existing layer");
 	}
 	return 0;
 }
 
 Sadly, this doesnt work, I get an Error: ArrayBoundsError upon inserting.
 Can anyone tell me how this is done, and maybe even where I can find 
 usful examples for more cmplex uses of arrays in D?
 
 My biggest problem ATM is the lack of good tutorials or examples, it 
 seems that D is no easy language to get started with, once you want to 
 do more than basics :-(

Does it work if you make this change? - if(layer <= layer_count) + if(layer < layer_map.length)
Jul 03 2008
parent reply Moritz <mpipahl gspgmbh.com> writes:
torhu schrieb:
 Does it work if you make this change?
 
 -     if(layer <= layer_count)
 +     if(layer < layer_map.length)

Well, my program DOES work, but I doesnt do what I want it to, because Im now unable to insert ScreenElements into the array. Do I need to initialize the array slots before I assign an object to them? The way I see it, the array has length 0 at start, and I cant put anything in slot 0 or Ill get an array out of bounds error :-( My problem is I dont know how to store the ScreenElement instances into the array. I guess my next problem after storing them will be to keep the garbage collector from deleting them after I leave the function where the ScreenElements are created and stored into the array, or does the array reference protect the ScreenElements from GC?.
Jul 03 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Moritz" <mpipahl gspgmbh.com> wrote in message 
news:g4jm5u$1p9r$1 digitalmars.com...
 torhu schrieb:
 Does it work if you make this change?

 -     if(layer <= layer_count)
 +     if(layer < layer_map.length)

Well, my program DOES work, but I doesnt do what I want it to, because Im now unable to insert ScreenElements into the array. Do I need to initialize the array slots before I assign an object to them? The way I see it, the array has length 0 at start, and I cant put anything in slot 0 or Ill get an array out of bounds error :-(

No, it's because you're using a temp variable when you shouldn't be. ScreenElement[] single_layer = layer_map[layer]; single_layer ~= new_element; That will get a reference the layer map at index `layer`, but when you concatenate, only the local single_layer will refer to the newer, longer array. Just do it in place: layer_map[layer] ~= new_element; (Also if you don't feel like typing all those long types for variables, it's completely unnecessary. auto single_layer = layer_map[layer]; Dah.)
 I guess my next problem after storing them will be to keep the garbage 
 collector from deleting them after I leave the function where the 
 ScreenElements  are created and stored into the array, or does the array 
 reference protect the ScreenElements from GC?.

Arrays are on the heap. As long as something references said array, the GC won't collect objects the array holds. That's kind of the point. The GC isn't out to make your life hard; quite the opposite in fact :) The GC is actually fairly conservative, and if it's not sure whether something is referenced or not (i.e. say you have some random-looking data, like sound data, and the GC says "hm, this looks like a pointer into an object"), it won't collect it.
Jul 03 2008
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Koroskin Denis" wrote
 On Fri, 04 Jul 2008 03:22:03 +0400, Jarrett Billingsley
 "Moritz" wrote
 torhu schrieb:
 Does it work if you make this change?

 -     if(layer <= layer_count)
 +     if(layer < layer_map.length)

Well, my program DOES work, but I doesnt do what I want it to, because Im now unable to insert ScreenElements into the array. Do I need to initialize the array slots before I assign an object to them? The way I see it, the array has length 0 at start, and I cant put anything in slot 0 or Ill get an array out of bounds error :-(

No, it's because you're using a temp variable when you shouldn't be. ScreenElement[] single_layer = layer_map[layer]; single_layer ~= new_element; That will get a reference the layer map at index `layer`, but when you concatenate, only the local single_layer will refer to the newer, longer array. Just do it in place: layer_map[layer] ~= new_element; (Also if you don't feel like typing all those long types for variables, it's completely unnecessary. auto single_layer = layer_map[layer]; Dah.)
 I guess my next problem after storing them will be to keep the garbage
 collector from deleting them after I leave the function where the
 ScreenElements  are created and stored into the array, or does the array
 reference protect the ScreenElements from GC?.

Arrays are on the heap. As long as something references said array, the GC won't collect objects the array holds. That's kind of the point. The GC isn't out to make your life hard; quite the opposite in fact :) The GC is actually fairly conservative, and if it's not sure whether something is referenced or not (i.e. say you have some random-looking data, like sound data, and the GC says "hm, this looks like a pointer into an object"), it won't collect it.

Or, better, use: auto single_layer = layer in layer_map; to avoid lookup on insertion: layer_map[layer] ~= new_element; -> single_layer ~= new_element; right?

According to an earlier post, layer_map is a 2D array, not an associative array. I think 'in' only works on AA's. What you could do though is: auto single_layer = &layer_map[layer]; But I'm not sure ~ works on an array pointer, but D does do some magical stuff with operators when dealing with pointers, so it could work :) -Steve
Jul 04 2008
prev sibling parent reply Moritz <mpipahl gspgmbh.com> writes:
Im sorry, but I still get an ArrayBoundsError upon doing:
layer_map[layer] ~= new_element;

Same goes for:
auto single_layer = &layer_map[layer];
*single_layer ~= new_element;

And whats the point of doing:
ScreenElement[][] layer_map = new ScreenElement[][5];

Do I HAVE to initialise a number of empty arrays before concatenating 
instances of classes into it or not?
I dont see the point in giving some lenght in an dynamic array, for this 
would make it static, or am I wrong?

My whole add_element() function looks like this, just to give you all 
the info:

int add_element(ScreenElement new_element, uint layer)
{
	writefln("layer: %d", layer);
	writefln("layer_map.length: %d", layer_map.length);
		
	if(layer <= layer_map.length)
	{

		auto single_layer = &layer_map[layer];
	        *single_layer ~= new_element;
	
		//comented out, enalbed this instead of the upper two lines as an 
alternative
	        //layer_map[layer] ~= new_element;
	}
	else
	{
		writefln("cant insert ScreenElement into non existing layer");
	}
	return 0;
}


 No, it's because you're using a temp variable when you shouldn't be.
 
 ScreenElement[] single_layer = layer_map[layer];
 single_layer ~= new_element;
 
 That will get a reference the layer map at index `layer`, but when you 
 concatenate, only the local single_layer will refer to the newer, longer 
 array.  Just do it in place:
 
 layer_map[layer] ~= new_element;
 
 (Also if you don't feel like typing all those long types for variables, it's 
 completely unnecessary.
 
 auto single_layer = layer_map[layer];
 
 Dah.)

Jul 04 2008
parent reply torhu <no spam.invalid> writes:
Moritz wrote:
 And whats the point of doing:
 ScreenElement[][] layer_map = new ScreenElement[][5];
 
 Do I HAVE to initialise a number of empty arrays before concatenating 
 instances of classes into it or not?
 I dont see the point in giving some lenght in an dynamic array, for this 
 would make it static, or am I wrong?

You need to add the layers before you can add ScreenElements to them. Do you have a fixed number of layers? Then what you suggested will work: ScreenElement[][] layer_map = new ScreenElement[][5]; If you are used to working with pointers, dynamic arrays are just that, except that they store the length of what the pointer points to too. It's only that some operations on them actually allocate memory. "~", "~=", and explicitly setting .length allocates. Indexing does not allocate.
 
 My whole add_element() function looks like this, just to give you all 
 the info:
 
 int add_element(ScreenElement new_element, uint layer)
 {
 	writefln("layer: %d", layer);
 	writefln("layer_map.length: %d", layer_map.length);
 		
 	if(layer <= layer_map.length)
 	{

Replace "<=" with "<", since layer_map.length always is one past the end of the array.
Jul 04 2008
parent reply Moritz <mpipahl gspgmbh.com> writes:
Thank you torhu, I finally managed to get something into this array! :-)

But I still dont understand if and how I can add a new ScreenElement 
array to the layer map *without* setting its size in advance(because I 
want to remain as generic as possible).

My original idea was to have a create_layer() function, which creates a 
new layer by adding an empty array to the layer map, so I can keep 
creating as many layers as I want to.

And another question: Can I modify the size of an array after I set it 
manually?


 You need to add the layers before you can add ScreenElements to them. Do 
 you have a fixed number of layers? Then what you suggested will work:
 
 ScreenElement[][] layer_map = new ScreenElement[][5];
 
 If you are used to working with pointers, dynamic arrays are just that, 
 except that they store the length of what the pointer points to too. 
 It's only that some operations on them actually allocate memory.  "~", 
 "~=", and explicitly setting .length allocates.  Indexing does not 
 allocate.

Jul 04 2008
parent reply torhu <no spam.invalid> writes:
Moritz wrote:
 Thank you torhu, I finally managed to get something into this array! :-)
 
 But I still dont understand if and how I can add a new ScreenElement 
 array to the layer map *without* setting its size in advance(because I 
 want to remain as generic as possible).

I'm wondering if you're aware what a two-dimensional array really is. When you do this: ScreenElement[][] layer_map = new ScreenElement[][5]; layer_map.length will be 5. But the lengths of the arrays in the second dimension will all be zero. For example, layer_map[0].length and layer_map[3].length will be zero. So you have allocated space for 5 arrays of ScreenElements, but no space for the ScreenElements themselves. Just 5 array references that don't have any space to refer to yet. I hope this makes sense to you.
 
 And another question: Can I modify the size of an array after I set it 
 manually?

Sure, these two will work anytime: array.length = whatever; // set length to whatever array ~= stuff; // increase length by 1, add 'stuff' at end
Jul 05 2008
parent reply Moritz <mpipahl gspgmbh.com> writes:
Thanks again, torhu. I understand multidimensional arrays (at least I 
think so :-) ), and that these arrays contain pointers to other arrays.

I thought the .length() operation would make the array static in its 
size, thats why I didnt try this earlier.

But after reading what you wrote, I still dont see why I cant go without 
the length(), by just using ~=, like:

ScreenElement[][]	layer_map;

int add_element(ScreenElement new_element, uint layer)
{
	layer_map[layer] ~= new_element;
}

You wrote setting the length and using ~= both increase the size of the 
array, but I get an ArrayBoundsError when using the ~=.

And thank you all for your help so far!!!!

torhu schrieb:
 Moritz wrote:
 Thank you torhu, I finally managed to get something into this array! :-)

 But I still dont understand if and how I can add a new ScreenElement 
 array to the layer map *without* setting its size in advance(because I 
 want to remain as generic as possible).

I'm wondering if you're aware what a two-dimensional array really is. When you do this: ScreenElement[][] layer_map = new ScreenElement[][5]; layer_map.length will be 5. But the lengths of the arrays in the second dimension will all be zero. For example, layer_map[0].length and layer_map[3].length will be zero. So you have allocated space for 5 arrays of ScreenElements, but no space for the ScreenElements themselves. Just 5 array references that don't have any space to refer to yet. I hope this makes sense to you.
 And another question: Can I modify the size of an array after I set it 
 manually?

Sure, these two will work anytime: array.length = whatever; // set length to whatever array ~= stuff; // increase length by 1, add 'stuff' at end

Jul 05 2008
next sibling parent torhu <no spam.invalid> writes:
Moritz wrote:
 Thanks again, torhu. I understand multidimensional arrays (at least I 
 think so :-) ), and that these arrays contain pointers to other arrays.
 
 I thought the .length() operation would make the array static in its 
 size, thats why I didnt try this earlier.
 
 But after reading what you wrote, I still dont see why I cant go without 
 the length(), by just using ~=, like:
 
 ScreenElement[][]	layer_map;
 
 int add_element(ScreenElement new_element, uint layer)
 {
 	layer_map[layer] ~= new_element;
 }
 
 You wrote setting the length and using ~= both increase the size of the 
 array, but I get an ArrayBoundsError when using the ~=.

That probably means you're not doing quite what you think you're doing. Try adding an assert and see if it gets triggered: int add_element(ScreenElement new_element, uint layer) { assert(layer < layer_map.length, "there's no layer with that number"); layer_map[layer] ~= new_element; }
 
 And thank you all for your help so far!!!!
 

My pleasure.
Jul 05 2008
prev sibling parent torhu <no spam.invalid> writes:
If you want more instant help, you could use IRC, it's #D on freenode.

Web-based IRC here:
http://embed.mibbit.com/?server=irc.freenode.org&channel=%23D
Jul 05 2008
prev sibling next sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Fri, 04 Jul 2008 03:22:03 +0400, Jarrett Billingsley  
<kb3ctd2 yahoo.com> wrote:

 "Moritz" <mpipahl gspgmbh.com> wrote in message
 news:g4jm5u$1p9r$1 digitalmars.com...
 torhu schrieb:
 Does it work if you make this change?

 -     if(layer <= layer_count)
 +     if(layer < layer_map.length)

Well, my program DOES work, but I doesnt do what I want it to, because Im now unable to insert ScreenElements into the array. Do I need to initialize the array slots before I assign an object to them? The way I see it, the array has length 0 at start, and I cant put anything in slot 0 or Ill get an array out of bounds error :-(

No, it's because you're using a temp variable when you shouldn't be. ScreenElement[] single_layer = layer_map[layer]; single_layer ~= new_element; That will get a reference the layer map at index `layer`, but when you concatenate, only the local single_layer will refer to the newer, longer array. Just do it in place: layer_map[layer] ~= new_element; (Also if you don't feel like typing all those long types for variables, it's completely unnecessary. auto single_layer = layer_map[layer]; Dah.)
 I guess my next problem after storing them will be to keep the garbage
 collector from deleting them after I leave the function where the
 ScreenElements  are created and stored into the array, or does the array
 reference protect the ScreenElements from GC?.

Arrays are on the heap. As long as something references said array, the GC won't collect objects the array holds. That's kind of the point. The GC isn't out to make your life hard; quite the opposite in fact :) The GC is actually fairly conservative, and if it's not sure whether something is referenced or not (i.e. say you have some random-looking data, like sound data, and the GC says "hm, this looks like a pointer into an object"), it won't collect it.

Or, better, use: auto single_layer = layer in layer_map; to avoid lookup on insertion: layer_map[layer] ~= new_element; -> single_layer ~= new_element; right?
Jul 04 2008
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Moritz" wrote
 So now I have a two dimensional array ready for my classes, but sadly, I 
 cant find any information on how classes can be stored in a 
 multidimensional array and how I can use the instances stored there.

 Ive just guessed and typed:

 int add_element(ScreenElement new_element, uint layer)
 {
 if(layer <= layer_count)
 {
 ScreenElement[] single_layer = layer_map[layer];
 single_layer ~= new_element;
 }
 else
 {
 writefln("cant insert ScreenElement into non existing layer");
 }
 return 0;
 }

 Sadly, this doesnt work, I get an Error: ArrayBoundsError upon inserting.
 Can anyone tell me how this is done, and maybe even where I can find usful 
 examples for more cmplex uses of arrays in D?

 My biggest problem ATM is the lack of good tutorials or examples, it seems 
 that D is no easy language to get started with, once you want to do more 
 than basics :-(

To help you understand, think of it this way: ScreenElement[][] is really a dynamic array of dynamic arrays. In otherwords, it means: (ScreenElement[])[]. So this starts out empty. In order to initialize it, say to size 5, you should do: ScreenElement[][] layer_map = new ScreenElement[][5]; Now, the map has 5 empty ScreenElement[] arrays in it. It's a lot easier to understand if you alias the ScreenElement[] type: alias ScreenElement[] layer; layer[] layer_map = new layer[5]; The thing about D that I like is that it is completely consistent in this regard. There are no 'special' cases, everything is broken down to the same simple case. Once you understand that, multi-dimensional arrays become really easy. -Steve
Jul 04 2008
prev sibling parent "Koroskin Denis" <2korden gmail.com> writes:
On Fri, 04 Jul 2008 17:40:12 +0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 "Koroskin Denis" wrote
 On Fri, 04 Jul 2008 03:22:03 +0400, Jarrett Billingsley
 "Moritz" wrote
 torhu schrieb:
 Does it work if you make this change?

 -     if(layer <= layer_count)
 +     if(layer < layer_map.length)

Well, my program DOES work, but I doesnt do what I want it to, because Im now unable to insert ScreenElements into the array. Do I need to initialize the array slots before I assign an object to them? The way I see it, the array has length 0 at start, and I cant put anything in slot 0 or Ill get an array out of bounds error :-(

No, it's because you're using a temp variable when you shouldn't be. ScreenElement[] single_layer = layer_map[layer]; single_layer ~= new_element; That will get a reference the layer map at index `layer`, but when you concatenate, only the local single_layer will refer to the newer, longer array. Just do it in place: layer_map[layer] ~= new_element; (Also if you don't feel like typing all those long types for variables, it's completely unnecessary. auto single_layer = layer_map[layer]; Dah.)
 I guess my next problem after storing them will be to keep the garbage
 collector from deleting them after I leave the function where the
 ScreenElements  are created and stored into the array, or does the  
 array
 reference protect the ScreenElements from GC?.

Arrays are on the heap. As long as something references said array, the GC won't collect objects the array holds. That's kind of the point. The GC isn't out to make your life hard; quite the opposite in fact :) The GC is actually fairly conservative, and if it's not sure whether something is referenced or not (i.e. say you have some random-looking data, like sound data, and the GC says "hm, this looks like a pointer into an object"), it won't collect it.

Or, better, use: auto single_layer = layer in layer_map; to avoid lookup on insertion: layer_map[layer] ~= new_element; -> right?

According to an earlier post, layer_map is a 2D array, not an associative array. I think 'in' only works on AA's. What you could do though is: auto single_layer = &layer_map[layer]; But I'm not sure ~ works on an array pointer, but D does do some magical stuff with operators when dealing with pointers, so it could work :) -Steve

You are right. It should be *single_layer ~= new_element; And yes, `in` doesn't work for dynamic arrays, although it could (for consistency and generality).
Jul 04 2008