Working with list in Monkey
Monkey Forums/Monkey Programming/Working with list in Monkey
| ||
Hello All, I have looked thru the whole set of list examples but I myself still don't understand why list are so much different from Blitzmax..! Does anyone have a better example of how to make list easier to work with in Monkey..? Fbepyon |
| ||
Could you be more specific? What is it that you think should be easier? |
| ||
We probably need a tutorial. But until then: Class CBullet Global bulletlist:List<CBullet> = New List<CBullet> Field x:Int, y:Int Global b:CBullet '' used for loops to deter GC Method New() bulletlist.AddLast(self) End Function Update() For b = Eachin bulletlist ''do something Next End End Or even: Class CBulletList Extends List<CBullet> ''add your custom Sort() here, if desired End ''then use Class CBullet Global bulletlist:CBulletlist = New CBulletlist ''...etc... End |
| ||
double post |
| ||
I don't know if this will help you but here is my 2 cents description:Class myClass .... End Class Local myList:List<myClass> ' this means you can only insert objects of Class 'myClass'. this works: Local myObject := New myClass myList.AddLast(myObject) this fails To compile: Local myObject := New otherClass myList.AddLast(myObject) ' this fails because it only supposed to accept "myClass" objects. you can only insert one type of objects as defined during the list Object creation. it will give an error otherwise. you can however store different class objects in the list If they have been extended from a common base Class such as in polymorphy. example: Class base .... End Class thisClass Extends base ... End Class thatClass Extends base ... End Local myList:List<base> Local thisObject:base = New thisClass myList.AddLast(thisObject) Local thatObject:base = New thatClass myList.AddLast(thatObject) To extract from the List For Local myObject:Tbase = Eachin myList If thisClass(myObject) Local this:thisClass = thisClass(myObject) 'process 'this' object Elseif thatClass(myObject) Local that:thatClass = thatClass(myObject) 'process 'that' object Endif Next hope this didn't confuse you even more. |
| ||
@AdamRedwoods Global b:CBullet '' used for loops to deter GC How does that deter GC? The object creation is in the ObjectEnumerator call that EachIn automatically does. From the official Monkey List class: Method ObjectEnumerator:Enumerator<T>() Return New Enumerator<T>( Self ) End |
| ||
How does that deter GC? The object creation is in the ObjectEnumerator call that EachIn automatically does. Mostly effects Java. When looking at the resulting code from the Java output, ObjectEnumerator is called once before the loop, so it doesn't effect the GC much. BUT-- If I use: For Local b:CBullet = Eachin bulletlist The loop will create a CBullet object each time. THEREFORE-- if I use the global variable like the above, the loop uses a static variable outside the loop, thus decreasing the number of times we create a new object (deterring GC). |
| ||
If this EachIn is being called even once every OnUpdate or OnRender, that's a hell of a lot of objects being created. Declaring a variable is not the same as instantiating an object. Can you post the generated Java code? |
| ||
This is what your class turns into:class bb__CBullet extends Object{ static bb_list_List bb_bulletlist; public bb__CBullet bb_CBullet_new(){ bb_bulletlist.bbm_AddLast(this); return this; } static bb__CBullet bb_b; static public void bb_CBullet_Update(){ bb_list_Enumerator bbt_=bb_bulletlist.bbm_ObjectEnumerator(); while(bbt_.bbm_HasNext()){ bb_b=((bb__CBullet)(bbt_.bbm_NextObject())); } } } And if you do the For Local bb:CBullet = Eachin bulletlist it turns into this: class bb__CBullet extends Object{ static bb_list_List bb_bulletlist; public bb__CBullet bb_CBullet_new(){ bb_bulletlist.bbm_AddLast(this); return this; } static public void bb_CBullet_Update(){ bb_list_Enumerator bbt_=bb_bulletlist.bbm_ObjectEnumerator(); while(bbt_.bbm_HasNext()){ bb__CBullet bbt_bb=((bb__CBullet)(bbt_.bbm_NextObject())); } } } Spot the difference |
| ||
From therevills' code:bb__CBullet bbt_bb=((bb__CBullet)(bbt_.bbm_NextObject()));This declares a local variable. It doesn't create an object. bb_list_Enumerator bbt_=bb_bulletlist.bbm_ObjectEnumerator();This creates an object within bbm_ObjectEnumerator(); Even one object created every loop is too many. Kudos for trying to optimise GC calls though. :) |
| ||
Ah, I see now. The only difference is the static definition. No GC. |
| ||
If this EachIn is being called even once every OnUpdate or OnRender, that's a hell of a lot of objects being created. just to clarify... it's not EachIn that creates the object, it's the class's ObjectEnumerator method that does. so we can easily use EachIn with pooled Enumerators. And in regard to the static/global outside the loop... the local declaration -inside- the loop will be faster even in Java as access to local variables and parameters in methods are much faster than access to static or instancefields. this is and has been a standard recommended performance enhancement. I know it seems counter intuitive but it comes down to the extra overhead a global requires and the fact that the local will most likely stay on register (and if not then the higher on the stack the better chance to stay in cache). *I have actually tested this although not on every device. edit: I should point out that if you really want to trimm everything then don't use EachIn even with pooled Enums... as there are the HasNext() function calls and also no way to unroll the loop. |
| ||
I thought NOT using globals would be faster as well, but for Java, I ended up with 10-20ms faster here. http://www.monkeycoder.co.nz/Community/post.php?topic=1226&post=11179 Overall, the differences are so minor that it doesn't matter. |
| ||
@dmaz just to clarify... it's not EachIn that creates the object, it's the class's ObjectEnumerator method that does @Samah This creates an object within bbm_ObjectEnumerator(); My point is that apart from arrays, all the enumerable system classes in Monkey create an object. I'm thinking of adding pooling to ArrayList, because at the moment it's still better to use Size and Get if you're targeting Android. Having said that, the Enumerator in ArrayList is a little more advanced than the official List one. It protects against concurrent modification, and if you manually retrieve it with .Enumerator(), you can traverse back and forth (indexed) and remove items dynamically. You can manually reset the enumerator to its default state by calling .Reset() |
| ||
@ AdamRedwoods That makes things alot better, and I was being stupid as it was because I was forgetting the SELF part of the classes (like blitzmax).. The reason I was wanting more information on the list is because I use it for all my map objects in my game.. Thanks All |
| ||
How do you find out the size of a list? |
| ||
Global propertyCards:List<fsProperty> = New List<fsProperty> Print propertyCards.Count() |