Simple Examples

Community Forums/Monkey2 Talk/Simple Examples

impixi(Posted 2016) [#1]
Here are some simple examples demonstrating a few of Monkey 2's language features. Hopefully self explanatory but let me know if not...

I'll post more examples later as I get the time.

(Not sure if I should post this thread here or on the Monkey2 dev forums?)

********
Pointers
********

pointers1.monkey2



pointers2.monkey2



*****************
Function Pointers
*****************

fp1.monkey2



fp2.monkey2



*****************
Generics
*****************

gen1.monkey2



gen2.monkey2




impixi(Posted 2016) [#2]
******************
Enumerated Types
******************

enum1.monkey2



enum2.monkey2




marksibly(Posted 2016) [#3]
Nice examples!

One thing to note is that you have to be *very* careful when using Varptr with 'class objects'.

A 'Ptr' wont keep an object alive GC-wise, so unless a normal variable is also keeping the object alive, there's a chance it will be GC'd 'behind your back'. I'd consider the pointer1.monkey2 example to be borderline dodgy for this reason - the 'obj1' var is, strictly speaking, 'dead' before the pointer is used. It'll work, but only because of how compilers work...

Also, an object var is already a pointer, ie: "sizeof( blah )" where blah is an instance of a class/interface will always return 4/8, so Varptr blah is sort of redundant for what I think I most people will instinctively want to use it for.

Varptr with a struct is also dangerous - but marginally less so, and it's a necessary evil for the sake of integrating with 3rd party stuff. Also, note that you can still cast 'extends void' objects to 'void ptr' (it's an automatic conversion in fact) so you still get to play with pointers when dealing with non-mx2 classes.

But I'm not sure it's a good idea with pure mx2 class objects, so I'm tempted to disallow it entirely. If you DO have to mess with pointers to mx2 objects, there is probably some native glue code involved so perhaps it's best to just leave that stuff for the glue code?

I do think a general, safe mechanism for dealing with 'variable references' (the one sensible use I can think of for Varptr obj) would be a very use feature though, and I do have a few ideas here. Raw pointers are a crappy way to achieve this though and one I don't really want to encourage.


impixi(Posted 2016) [#4]
Thanks for the info, Mark!


But I'm not sure it's a good idea with pure mx2 class objects, so I'm tempted to disallow it entirely. If you DO have to mess with pointers to mx2 objects, there is probably some native glue code involved so perhaps it's best to just leave that stuff for the glue code?



Yep, I'd agree with that.

EDIT: I put a little note in the pointers1.monkey2 example.


impixi(Posted 2016) [#5]
******************
Lambda Functions
******************

lambda1.monkey2



lambda2.monkey2




impixi(Posted 2016) [#6]
**************
External C
**************

Place all files in the same folder and run exte1.monkey2.

utils.h



utils.c



utils.monkey2



exte1.monkey2



EDIT (22-Mar-16): Finally had a chance to test this on a Mac - fixed a bug in utils.h and utils.c and it now runs okay...


impixi(Posted 2016) [#7]
**************
Operator Overloading
**************
opover1.monkey2



opover2.monkey2



**************
Struct
**************

struct1.monkey2



struct2.monkey2



EDIT (27 Mar 2016): Updated opover2.monkey2 to overload the <=> operator.


impixi(Posted 2016) [#8]
********************
Abstract Class
********************

ab1.monkey2




kmac(Posted 2016) [#9]
This is great. I have a few hard deadlines over the next few days but will definitely study these next week.


marksibly(Posted 2016) [#10]
Great stuff!

A quick comment re: comparison overloads: you only need to overload Operator<=> to implement ALL comparisons. This is very convenient and something people should probably know about.


impixi(Posted 2016) [#11]
@Mark:

Wouldn't that only work for sorting-relating comparisons? The result of a <=> comparison can be -1, 0, or +1. Useful to determine whether a given value is less than, equal to, or greater than another given value.

The >, <, <> and = comparisons return either true (1) or false (0). How could I overload <=> so that all those checks would present the correct boolean result when used, for example, in an If statement?

I've experimented with my opover2.monkey2 example above but just cannot think how to make it work. It's probably something obvious I'm overlooking, so apologies in advance. ;)


marksibly(Posted 2016) [#12]
Basically, "X op Y" is transformed to "(X<=>Y) op 0" where op is one of <, >, <= etc.

So "5<8" is transformed to "(5<=>8)<0" and "p>=q" is transformed to "(p<=>q)>=0" etc.

If you think it through it works!

So you should be able to replace your 3 operators with:

Operator<=>:Int( o2:MyClass )
Return Self._value<=>o2._value
End

...which is really doing the same thing as...

Operator<=>:Int( o2:MyClass )
If Self._value<o2._value Return -1
If Self._value>o2_value Return 1
Return 0
End

Note also that the compiler 'writes' a version of <=> for structs (but yours is a class...) that don't already have one. This applies <=> to all members, and returns the first non-0 result. If there is no non-0 result, it returns 0. For classes, the default '<=>' simply subtracts pointers.

You can actually derive all comparisons with just '<' (or '>' ), eg:

"x>y" -> "y<x"
"x<>y" -> "x<y or y<x"
"x=y" -> "not (x<y or y<x)"

...etc. but I thought adding "<=>" would be simpler to understand and more flexible/useful. Also, the '<' approach can result in 2 operator method calls for some comparisons (although those methods would probably be simpler).


Pakz(Posted 2016) [#13]
Keep em coming! :D


impixi(Posted 2016) [#14]
@Mark

Thanks for the explanation! Your logic seems correct. However...


So you should be able to replace your 3 operators with:

Operator<=>:Int( o2:MyClass )
Return Self._value<=>o2._value
End



That's the first thing I tried but it produces incorrect results in my example (which is why I thought overloading <=> might be more involved than I assumed).

The original opover2.monkey2 produces the following output (correct).


Gold > Silver
Gold <> Silver



A modified version, simply commenting out the <, >, and = overloads and adding the above <=> overload produces:


Gold < Silver
Gold <> Silver



That is incorrect. Altering the initial values also produces incorrect results for most combinations (whereas the original code produces correct results).

@Pakz:

Off the top of my head, I still need to write some Interface examples. Maybe some String and Array initialization and manipulation examples. I do have a more advanced Extern example "completed", except for one remaining bug I haven't yet squashed.

Any other MX2 language-related items I should write examples for?


tiresius(Posted 2016) [#15]
These are great!!! You covered all the topics I wondered about for Monkey2. If there are any others that would be cool, too!


Pakz(Posted 2016) [#16]
I wonder how mx2 has the arrays done. This is something I use a lot.
2 dimensional arrays, 3 dimensional arrays, 2 dimensional data (tilemap) in a array.


marksibly(Posted 2016) [#17]
> That's the first thing I tried but it produces incorrect results in my example (which is why I thought overloading <=> might be more involved than I assumed).

It's a bug! Found and fixed, will github soon.

There are likely to be a bunch of little things like this still in there, so if something looks like it should be working but isn't, chances are pretty good that it's my fault, not yours! So please let me if you discover any other issues like this in future. Even if it's not a bug, if it's confusing or inconsistent that's worth checking out too.


marksibly(Posted 2016) [#18]
> 2 dimensional arrays, 3 dimensional arrays, 2 dimensional data (tilemap) in a array.

2+ dimensional arrays are supported, but not as well as 1d yet.

You can create and index them using...

Local t:=New Int[10,20]
Print t[5,5]

...but you can't yet create them using 'New Int[](...)' syntax, or slice them etc. I'm not sure yet how much you'll be able to do with them, but they will at least be in there.


marksibly(Posted 2016) [#19]
Ok, I've pushed the fix for Operator<=> to github.


tiresius(Posted 2016) [#20]
For some reason I thought arrays would be the same as Monkey1, good to know.
This makes more sense to my brain than the "array of arrays" we had earlier.


Pakz(Posted 2016) [#21]
So it's

Local t:=New Int[10,20,3]
Print t[5,5,0]

for a 3 dimensional array?

Is easier then in monkey 1.

The tilemap data I put in 2 dimensional arrays since there is no read data in monkey 1 afaik.


marksibly(Posted 2016) [#22]
Here's a little 'LoadMap2d' demo that uses a JSON file to store data.

Note: it requires the latest version of mx2cc on github - just fixed a few array issues.

'----- loadmap2d.monkey2 -----


'----- map2d.json -----



impixi(Posted 2016) [#23]

Ok, I've pushed the fix for Operator<=> to github.



Thanks. Now it works as expected.

PS: I like the new documentation layout, linked to and described in the MX2 dev blog. The logo is cool too...


impixi(Posted 2016) [#24]
***********
Interfaces
***********

inter1.monkey2




impixi(Posted 2016) [#25]
**************
External C++
**************

Place all files in the same folder and run exte2.monkey2.

cpprand.h



cpprand.cpp



cpprand.monkey2



exte2.monkey2