Simple Examples
Community Forums/Monkey2 Talk/Simple Examples
| ||
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 |
| ||
****************** Enumerated Types ****************** enum1.monkey2 enum2.monkey2 |
| ||
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. |
| ||
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. |
| ||
****************** Lambda Functions ****************** lambda1.monkey2 lambda2.monkey2 |
| ||
************** 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... |
| ||
************** Operator Overloading ************** opover1.monkey2 opover2.monkey2 ************** Struct ************** struct1.monkey2 struct2.monkey2 EDIT (27 Mar 2016): Updated opover2.monkey2 to overload the <=> operator. |
| ||
******************** Abstract Class ******************** ab1.monkey2 |
| ||
This is great. I have a few hard deadlines over the next few days but will definitely study these next week. |
| ||
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. |
| ||
@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. ;) |
| ||
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). |
| ||
Keep em coming! :D |
| ||
@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? |
| ||
These are great!!! You covered all the topics I wondered about for Monkey2. If there are any others that would be cool, too! |
| ||
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. |
| ||
> 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. |
| ||
> 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. |
| ||
Ok, I've pushed the fix for Operator<=> to github. |
| ||
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. |
| ||
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. |
| ||
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 ----- |
| ||
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... |
| ||
*********** Interfaces *********** inter1.monkey2 |
| ||
************** External C++ ************** Place all files in the same folder and run exte2.monkey2. cpprand.h cpprand.cpp cpprand.monkey2 exte2.monkey2 |