Reference functions

Monkey Forums/Monkey Programming/Reference functions

lejmer(Posted 2012) [#1]
Is it possible to reference a function in Monkey? Like having a function as a parameter of another function?

Something like:

[monkeycode]
Function Test:Void(myFunc:Int(param1:Int, param2:Int))

myFunc(1, 2)

End
[/monkeycode]

You could do this in BlitzMax, if I remember correctly.


lejmer(Posted 2012) [#2]
The reason I ask is that I am trying to use Singletons like you do in C++, like so:

// Singleton.h
template <class T>
class Singleton
{
public:
	static T& instance()
	{
		static T _instance;
		return _instance;
	}
private:
	Singleton();
	~Singleton();
	Singleton(Singleton const&);
	Singleton& operator=(Singleton const&);
};

// MyClass.h
#include "Singleton.h"

class MyClass
{
public:
	int member;
}

#define sMyClass Singleton<MyClass>.instance()

// main.cpp
#include "MyClass.h"

int main()
{
	sMyClass.member = 5;
	return 0;
}


My attempt to implement the simpleton class in Monkey worked fine:

[monkeycode]
' Singleton.monkey
Strict

Class Singleton<T>

Function instance:T()

If (_instance) Return _instance

_instance = New T
Return _instance

End

Method New()
End Method

Global _instance:T

End
[/monkeycode]

Now all that's left is the #define part, but we don't have that preprocessor directive in Monkey, so first I tried Alias. Turns out Alias doesn't work like that. Next I thought I'd reference the instance function instead. Something like:

[monkeycode]
' MyClass.monkey
Strict

Import Singleton

Class MyClass

Field member:Int

End

Global sMyClass:MyClass() = Singleton<MyClass>.instance
[/monkeycode]
[monkeycode]
' main.monkey
Strict

Import MyClass

Function Main:Int()

sMyClass().member = 5;

End
[/monkeycode]


Tibit(Posted 2012) [#3]
It is simpler than that!
import myClass

[monkeycode]
Function Main:Int()

MyClass.member = 5;

End
[/monkeycode]
------------ myClass.monkey -----------
[monkeycode]
Global MyClass:MyClassSingleton = new MyClassSingleton
Class MyClassSingleton
Field member:Int
End
[/monkeycode]
---------------------------------------

That class will ONLY be created IF you mention that class anywhere in your code seen from the initial Main:Int() file + imports.

Meaning that if you have 500 Globals like that in one file and you only mention one, only that one will ever be translated and instaciated.

In my oppinion it is not the exact same as a Singleton, but to me it is better in most cases.


lejmer(Posted 2012) [#4]
That's true Tibit, thanks for that! Will go that route for this project.

However, function pointers, or function references would be very much appreciated for other purposes. I hope Mark implements it in a future update.


invaderJim(Posted 2012) [#5]
You can get references to functions using reflection:

[monkeycode]
Import reflection

Function PrintSomething()
Print("Hello World")
End

Function DoFunction(func:FunctionInfo)
func.Invoke([])
End

Function Main()
Local func:FunctionInfo = GetFunction("PrintSomething",[])

DoFunction(func)
End
[/monkeycode]

You can also get at methods and functions within classes, and anything else! There's a nice little write-up in the documentation for the reflection module, or you can check out my videos on reflection if you want to find out more. There's a lot you can do with it :)


Tibit(Posted 2012) [#6]
invaderJim, are reflection safe to use performance wise for non-debug stuff? I'm still thinking about reflection from C#, and I fear that.

And on the subject of function references, or having functions as objects. There is a lot of cool things that can be done with that and certainly something that I'd like. Maybe reflection is the solution there?

I strongly recommend Jim's videos btw, they are great!


lejmer(Posted 2012) [#7]
Yeah reflection is a nice workaround and if I ever need to reference functions I will be sure to use it :) But reflection is slow. That is the downside of it. Thanks for sharing though! If it is not implemented this is the only way to do it! :)


invaderJim(Posted 2012) [#8]
It's certainly slower than a direct reference, yeah, but I wouldn't discount it completely. It really just depends on what you're doing.

If I ever get worried about performance, I just wrap my functions in classes and reference them that way.


lejmer(Posted 2012) [#9]
Haha, never thought of referencing them by wrapping them in classes. Good idea! :)


Shinkiro1(Posted 2012) [#10]
[monkeycode]
Interface Callback
Method Execute:Void (args:Object[])
End

Class SampleFunction Implements Callback
Method Execute:Void (args:Object[])
'Your function code here
End
End
[/monkeycode]

Only drawback is you have to create the class.