Function Returns a Function?

BlitzMax Forums/BlitzMax Programming/Function Returns a Function?

Gabriel(Posted 2007) [#1]
Is it possible to have a function return a function? I mean we have function pointers which we can store in a standard variable, so it stands to reason that at one point you're going to fancy filling that variable from a function, but I can't find a way to define it such that BlitzMax doesn't complain. Passing back a Byte Ptr just isn't as userfriendly somehow.


TaskMaster(Posted 2007) [#2]
Yes, you can pass a function in a function. Just leave the parenthesis off. I have done it.

I would post an example, but I do not have any of my code with me, I left my removeable hard drive at home this morning with my BlitzMax install and all of my code on it.


grable(Posted 2007) [#3]
Function fun:Int()()
	Function sub:Int()
		Return 1
	EndFunction	
	Return sub
EndFunction

Local f:Int() = fun()
Print f()
print fun()()
;)


CS_TBL(Posted 2007) [#4]
What kind of purposes is this handy for?


Gabriel(Posted 2007) [#5]
Grable, thanks, that works, but only if the function prototypes match. What happens if Fun takes no parameters ( as in your example ) but Sub should take three floats?


H&K(Posted 2007) [#6]
No gab, when you pass a funtion pointer you are under the same restriction as if you wanted to return an ordinary type. That is if you declare the function as INT it returns INT, if you say return AFUNC:fn(Int,Int)() then it needs to return FN(int,int)
You deal with this exactly the way you would deal with wnating to return different types. (ie pass a pointer to a TLink for example)


Gabriel(Posted 2007) [#7]
H&K, I think you're confusing the functions. I'm talking about the function which returns a function. It should not require the same parameters as the function it's returning.


H&K(Posted 2007) [#8]
I'm talking about the function which returns a function. It should not require the same parameters as the function it's returning.
Yep. Sorry to have missunderstood you. Your right.

What I was saying was that all the returned functions need to have the same footprint


Gabriel(Posted 2007) [#9]
Yes, it's precisely that requirement that I'm trying to enforce, rather than having loose Byte Ptr's floating around in my functions.


marksibly(Posted 2007) [#10]

What happens if Fun takes no parameters ( as in your example ) but Sub should take three floats?



Strict

Function fun:Int( x,y,z) ()
	Function sub:Int( x,y,z )
		Return x+y+z
	EndFunction	
	Return sub
EndFunction

Local f:Int( x,y,z ) = fun()
Print f( 1,2,3 )
print fun()( 4,5,6 )



Gabriel(Posted 2007) [#11]
Aha, thanks Mark. That's just what I needed.


CS_TBL(Posted 2007) [#12]
but...
What kind of purposes is this handy for?

I know what functionpointers are for, and *Mark* give us method pointers plz!, but what's a typical use of a function returning a functions (preferably in context of apps)?


Gabriel(Posted 2007) [#13]
What kind of purposes is this handy for?


Oh yes, sorry.

When you need to get a function pointer. Normally you would just make it a variable assignment but like anything, if you use the same chunk of code in several areas of your program, it's sensible to make it into a function. I need to do this in many places, so it made more sense to make it a function, then if it ever has to be changed, it only has to be changed once.


Azathoth(Posted 2007) [#14]
I can see it being more useful if there were lambda functions like in Python.


H&K(Posted 2007) [#15]
I use it so as to get the Function that I want the timer hook to errr... hook. Then as I want the main hook to call the sub hooks, I have an array of pointers that are called at times. These obviously can (and in fact are ), pre defined, and so I have functions that return which are to be called when.

At some point during my main timing cycle (1 sec normaly), I precalculate which Functions are going to be called and how often, so need function pointers to be returned.

(To be honest its a fudge, and Id much rather multiprocess, which is really what Im faking)

PS, Its probably not the best way to do it, but its working, so I dont mess with it)


TaskMaster(Posted 2007) [#16]
I used it to make a button class. I pass the button the function it should call when it gets clicked. Works great.


CS_TBL(Posted 2007) [#17]
o_O Wouldn't it be more elegant to have that function listening to an event sent by that button?


TaskMaster(Posted 2007) [#18]
More elegant? Not sure about that.

I create a Function Button_Clicked() then give that function to the button, when it is clicked, the function gets called. No worrying about looping looking for events.


Azathoth(Posted 2007) [#19]
Isn't that basically a callback? Atleast what you've described doesn't sound like a function returning a function pointer.


Blueapples(Posted 2007) [#20]

I can see it being more useful if there were lambda functions like in Python.



I think you mean like in LISP (Lambda expressions). ;-)


Azathoth(Posted 2007) [#21]
Lua has them too, I knew someone would bring up lisp though.


N(Posted 2007) [#22]
o_O Wouldn't it be more elegant to have that function listening to an event sent by that button?

Not really. This way, you can assign the function to different buttons and have them all handled accordingly, instead of writing a function to look for specific buttons. Overall, it makes the code less complicated in one way and more complicated in another. Depends on what you want, obviously.


Dreamora(Posted 2007) [#23]
Not sure if function pointers would be the wisest decision to use in event handling as function points still are not the best idea when it comes to "keep the code fast" ... normally I would say use function templates instead but BM sadly does not have them nor delegates/agents ...


TaskMaster(Posted 2007) [#24]
Here is how I am currently using the original posters question.

This function creates a stack of cards. The final three parameters are what functions the stack will call if the user drops on or drags from or dblclicks on the stack.

Discard=TCards.NewStack(110,10,4,1,Null,TopDrag, DblCLick)

So, when a player tries to drag cards from the Discard stack, TopDrag is called and returns a true or false of whether or not the player can drag that particular card.


H&K(Posted 2007) [#25]
normally I would say use function templates instead but BM sadly does not have them nor delegates/agents
LoL


(@dream, just made me laugh, not having a go at you)


Gabriel(Posted 2007) [#26]
For a simple Game GUI I think function pointers are perfect. Readable and clean, easy to implement. I wouldn't use it for a complex app-style GUI, but for a few buttons and widgets in a game, I think they're ideal.


Picklesworth(Posted 2007) [#27]
What's wrong with them in a complex GUI?

Done right, function pointers are a fantastic way to achieve event-oriented programming, which (when done right, eg: Not Flash / Actionscript), is quite a pleasant interface.

Of course, judging by my recent "discoveries," I still have a lot to learn :)


Gabriel(Posted 2007) [#28]
Nothing is wrong with them, I just wouldn't use them in a complex GUI. Personal preference. If I was writing a complex GUI, I'd either do it the MaxGUI way, or possibly script it. I have a GUI pretty much complete now, but I think if I was starting again from scratch, I'd probably go with XML and Lua, for layout and events respectively.