Let's say I want to extend the list type...

Community Forums/Monkey Talk/Let's say I want to extend the list type...

sswift(Posted 2011) [#1]
What syntax would I use to do this, while still retaining the class parameter which allows me to use the class with any type of object?

In other words, if I have:

Class List<T>

Would I do this:

Class ListB<T> Extends List

Or this?

Class ListB<T> Extends List<T>

Or something else?

Last edited 2011


Jesse(Posted 2011) [#2]
had to do a quick test wasn't sure:

Strict
Import Mojo
Class Blist<T> Extends List<T>

End Class

Class myClass
	Field a:Int = 5
End Class


Function Main:Int()
	Local list := New Blist<myClass>
	Local this := New myClass
	list.AddLast(this)
	Local that:myClass = myClass(list.Last())
	Print that.a
End Function


Last edited 2011


sswift(Posted 2011) [#3]
[edit]

Nevermind, figured it out.

Last edited 2011


sswift(Posted 2011) [#4]
I get missing return expression when I try to run that. And when I remove the :Int from main, like in the horsey example, I get a syntax error.

[edit]

I think it's the strict setting that causes the error with main. Horsey doesn't have that. If I comment out the classes it doesn't error on the main declaration if I put the :Int back. But of course it errors on the rest of the code.

Last edited 2011


sswift(Posted 2011) [#5]
Strict
Import Mojo


Class Blist<T> Extends List<T>
End 

Class myClass
	Field a:Int = 5
End
 
Function Main:Int()
End


"missing return expression" on Function Main:Int()


sswift(Posted 2011) [#6]
Okay, apparently with strict on, I have to have Return 0 in the function. It won't simply assume I want it to return 0.

Last edited 2011


Yasha(Posted 2011) [#7]
Well that seems reasonable. If specified the return type as an Int, it expects that you're going to return an Int. Monkey is kind enough to add a Void return type for functions that don't return anything; perhaps you can use that?

(Haven't tested; some languages don't allow Main to be Void though.)


sswift(Posted 2011) [#8]
Okay, so it's running now, but the output from Print doesn't appear in either the output window or firefox when the app is run.


sswift(Posted 2011) [#9]
"Well that seems reasonable. If specified the return type as an Int, it expects that you're going to return an Int."

No language I've ever used has required me to provide a return value. And requiring one results in situations like this:

Function Main:Int()
Local a:Int = 5
If a = 5 Return 0 Else Return 1
End

That won't compile, even though a value is always returned. I'm forced to put a return value at the end of the function even though the code will never be executed.

Last edited 2011


Matty(Posted 2011) [#10]

Function Main:Int()
Local a:Int = 5
If a = 5 Return 0 Else Return 1
End



Compiles fine for me...


sswift(Posted 2011) [#11]
I'm using the demo. Perhaps it was fixed?

[edit]

No, that particular piece of code compiles fine on my end too. What the hell...

Last edited 2011


Jesse(Posted 2011) [#12]
the demo is quite outdated as you can guess my demo works fine here with the latest version.

Last edited 2011


sswift(Posted 2011) [#13]
Ah, the issue is I didn't put Strict on the example code.

Try this:
Strict

Function Main:Int()
Local a:Int = 5
If a = 5 Return 0 Else Return 1
End



sswift(Posted 2011) [#14]
Just because it works fine on your end doesn't mean the demo is broken. Where am I supposed to see the print statements? If it is in the web browser, then perhaps you're not using Firefox? I would not expect the print statement of all things to be broken in the demo.


Jesse(Posted 2011) [#15]
it displays on my browser just below 480th pixel.
Safari

Last edited 2011


therevills(Posted 2011) [#16]
http://www.monkeycoder.co.nz/Community/posts.php?topic=135

Print statements should show up under the application in the text area when running HTML5.

In Flash they appear on top of game. In GLFW, XNA and STDCPP they appear in the console.


Jesse(Posted 2011) [#17]
sswift is using the the demo but it has no reason to fail.

What I am wondering is why does it compile if I didn't put a return in the main Function.


therevills(Posted 2011) [#18]
LOL - I've downloaded the demo and compiled the following code:

Strict
Import Mojo


Class Blist<T> Extends List<T>
End 

Class myClass
	Field a:Int = 5
End
 
Function Main:Int()
End


In the demo it complains with Missing return expression, in the full version (v44) it compiles fine... I would say its a bug with the new version of Monkey.

[edit]
I've just raised it in Monkey bugs forum:
http://www.monkeycoder.co.nz/Community/posts.php?topic=1370
[/edit]

Last edited 2011


sswift(Posted 2011) [#19]
Is <T> special in some way, or can I use any name there that isn't already assigned to a class?


Jesse(Posted 2011) [#20]
it's not that hard to do some tests:
Strict
Import Mojo
Class Blist<T> Extends List<otherClass>

End Class

Class myClass
	Field a:Int = 5
End Class

Class otherClass
	Field b:String = "ok this is it"
End Class

Function Main:Int()
	Local list := New Blist<otherClass>
	Local foo := New otherClass
	list.AddLast(foo)
	Local that := otherClass(list.Last())
	Print that.b
	Local this := New myClass
	'list.AddLast(this)
	
End Function

uncomment the last line and you will get it.

Last edited 2011


sswift(Posted 2011) [#21]
Ugh. Trying to extend monkey's list type to fix it's shortcomings is a pain in the ass. It's quickly 10x as much work as it would be to just copy the type and modify it.

The whole <T> thing confuses the hell out of me. I understand how to use it in the simple case of creating a new list of objects, but it's impossible to decide where I need to add it when extending the type to create a new list type.

Also, I ran into a problem with nodes. There's no methods to get the next and previous nodes in the list. And I don't know if I can fix that by extending the node class. I think maybe if I typecast the new node type over pointers to the nodes, it might work... but... ugh.

There is just no good solution. Adding a new method to a preexisting class should not be this complicated. Why can't I just declare the class again in my code with some other keyword, and stick the new methods and fields in there and be done with it?

I think I'll just fix the List class and name it something else and wash my hands of the whole thing.

Last edited 2011


Jesse(Posted 2011) [#22]
what exactly are you trying to do? maybe someone here or I can help.


sswift(Posted 2011) [#23]
I am trying to add a merge sort to the List class.

I wanted to make it a generic extension to the class so anyone could use it to sort a list of any kind of object, rather than simply copying the list code and making something specific to my needs.


sswift(Posted 2011) [#24]
Here is the original code in BlitzMax:




sswift(Posted 2011) [#25]
And here is the code I've partially converted to Monkey, after I removed all the <T> crap I'd added which was making it impossible for me to follow. (I was gonna try adding it back once I made sure the function actually worked.)




sswift(Posted 2011) [#26]
I'm also trying to clean the code up a bit.

Where the original function required you to set a function pointer to the compare function, I was gonna require a compare method in the class you have in the list.

And where there was a parameter in the sort() method where the size of the list was passed internally, I thought it would be better to hide that from the user and store the size of the list in the list for easy retrieval. But that would require overriding the functions which add and delete nodes and I'm not sure if I can call the original code after I override the method. If I can't do that to patch my counter in there, then I'd have to copy the code from the original methods. And I don't like that solution.

It seems like the easiest thing to do is just copy the list class whole hog, and simply modify it. Trying to override and extend everything just for the sake of using the original list class just in the off chance Mark at some point decides to add some new functionality is just going to make ugly and hard to maintain code.


Jesse(Posted 2011) [#27]

I think I'll just fix the List class and name it something else and wash my hands of the whole thing.



I think you are better of that way.

The thing that makes it hard to extend classes is the use of Private. I think that when making public modules one should not put/use "Private" specially when declaring the module as public domain.
It really makes no cense to me. the only way to resolve the problem is to remove the private from the list. the problem is that every time an update is done we have to make sure the list is modified again.

What you want to do can be done but by modifying the List.monkey file. But if you are going to do that, might as well do as you suggested.


AdamRedwoods(Posted 2011) [#28]
This was actually a problem I found with the current List Class (v44), having no access to Nodes previous and forward to manually iterate through a list (or partially iterate).
I had to create a whole new ListMod with it's own Node Class allowing me to use Node.GetNext() and Node.GetPrev().

Not hard to do since you basically just copy the file and do an Import, but yes, private fields limit Extendibilty.

Last edited 2011


therevills(Posted 2011) [#29]
I did this (created my own list type which was a copy and paste of the Monkey List) when I wanted a sort rountine...

These days I just use Diddy's Arraylist... since I know when it will create an object or not - which you really need to watch out for on Android.


sswift(Posted 2011) [#30]
"These days I just use Diddy's Arraylist... since I know when it will create an object or not - which you really need to watch out for on Android."

Can you elaborate on this?


therevills(Posted 2011) [#31]
Which part? ;)

Diddy's Arraylist uses an array which you can add to, much like a List, but it doesnt use nodes etc. Its based of the Java ArrayList.

In Android you dont want to create objects when you are playing your game (in the main gameplay part anyway), as when you call "new" it gives the GC a chance to run and it will hurt your FPS. Its best to set up all your objects before the game starts and reuse them overtime.


Gabriel(Posted 2011) [#32]
I can confirm that you definitely do not want to be creating and destroying objects on a per-frame basis on Android (or iOS for that matter.) Object pooling is a must for dynamic objects.