digitalmars.D.learn - Library writing - delegates or fp's?
- Chad J (64/64) Jun 20 2006 So I have decided to roll my own GUI library, one dedicated to computer
- Derek Parnell (47/60) Jun 20 2006 It doesn't have to be as complex as that. All you need to do to turn
- Chad J (22/44) Jun 20 2006 Pretty nice, but then I can't do something like this:
- Derek Parnell (29/37) Jun 20 2006 ...
- Chad J (4/36) Jun 20 2006 Indeed. That kicks ass.
- Carlos Santander (5/49) Jun 21 2006 I thought the frame pointer would get lost and cause a segfault later on...
- Bruno Medeiros (7/37) Jul 18 2006 The frame pointer becomes invalid, but that is no problem since the
- Carlos Santander (5/41) Jul 21 2006 In this case, yes, you're right. I must admit I didn't notice that. Howe...
- Lionello Lunesu (12/24) Jun 21 2006 At the moment, a function can't be cast to a delegate, but I think this
- BCS (17/22) Jun 21 2006 [...]
- Andrei Khropov (3/34) Jul 18 2006 maybe just "cast(delegate)&fn" in the spirit of inferred typing?
- BCS (3/20) Jul 18 2006 That /would/ be better.
- Don Clugston (6/17) Jul 19 2006 It works fine *most of the time*. IIRC, sometimes it will result in
- BCS (4/25) Jul 25 2006 I wouldn't use it (if possible) even if it was portable. The compiler
So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates? I suppose I could choose one or the other, but I think it desirable to allow use of both since I don't want to force the user of the library into a particular style or make them use ugly workarounds. I am currently thinking of a few possible solutions, none of which look very pleasing to me: programming. Example - import std.stdio; int delegate(int) increment; void main() { Dummy d = new Dummy(); increment = &d.classIncr; writefln( increment(1) ); } int incr( int a ) { return a + 1; } class Dummy { this() {} int classIncr( int a ) { return incr(a); } } function pointer or a delegate, but is kinda clumsy to deal with. EX: import std.stdio; alias CallBack!(int function(int,Object)) IncCallBack; IncCallBack increment; void main() { increment.functionPointer = &incr; writefln( increment.functionPointer(1,null) ); } int incr( int a ) { return a + 1; } struct CallBack( fpType ) { Object object = null; fpType functionPointer; static CallBack!(fpType) opCall( fpType fp ) { CallBack!(fpType) result; result.functionPointer = fp; return result; } } naming convention. I suppose there could be a better naming convention here, but it seems hackish as well. EX: void delegate(int,int,ubyte) mouseButtonUp_dg; void function(int,int,ubyte) mouseButtonUp_fp; Maybe I'm missing something obvious. I'd appreciate it if someone has a better solution than any of these. Otherwise I'll settle for some wise advice from those who have already been here :)
Jun 20 2006
On Wed, 21 Jun 2006 00:40:15 -0400, Chad J wrote:So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates? I suppose I could choose one or the other, but I think it desirable to allow use of both since I don't want to force the user of the library into a particular style or make them use ugly workarounds. I am currently thinking of a few possible solutions, none of which look very pleasing to me: programming. Example -It doesn't have to be as complex as that. All you need to do to turn module-level functions into delegates is to place them inside the module's constructor or any other function for that matter, including main(). For example .. import std.stdio; int delegate(int) increment; static this() { int incr( int a ) { return a + 1; } increment = &incr; } void main() { writefln( increment(1) ); } Or if you prefer the new function literal syntax (and not use the module constructor) ... import std.stdio; int delegate(int) increment; int delegate(int) decrement; void Init_Delegates() { increment = delegate int ( int a ) { return a + 1; }; decrement = delegate int ( int a ) { return a - 1; }; } void main() { Init_Delegates(); writefln( increment(1) ); writefln( decrement(1) ); } -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 21/06/2006 3:18:11 PM
Jun 20 2006
Derek Parnell wrote:It doesn't have to be as complex as that. All you need to do to turn module-level functions into delegates is to place them inside the module's constructor or any other function for that matter, including main(). For example .. import std.stdio; int delegate(int) increment; static this() { int incr( int a ) { return a + 1; } increment = &incr; } void main() { writefln( increment(1) ); }Pretty nice, but then I can't do something like this: import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } static this() { int incr( int a ) { return a + 1; } increment = &incr; } I'm thinking incase someone wanted to say, have a mouse handling function be triggered by the GUI's delegate and also have it artificially triggered by some other code via a direct function call (maybe a tutorial, debug routine, or something like that). I suppose they should just call the delegate though. I like it. Thanks.
Jun 20 2006
On Wed, 21 Jun 2006 02:12:54 -0400, Chad J wrote:Pretty nice, but then I can't do something like this:...writefln( increment(1) ); writefln( incr(2) );...I'm thinking incase someone wanted to say, have a mouse handling function be triggered by the GUI's delegate and also have it artificially triggered by some other code via a direct function call (maybe a tutorial, debug routine, or something like that).Sure you can! How about this ... import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } int incr( int a ) { return a + 1; } static this() { increment = delegate int ( int a ) {return incr(a); }; } Would that do?I suppose they should just call the delegate though. I like it. Thanks.Yeah, I guess you could do that as well. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 21/06/2006 4:20:09 PM
Jun 20 2006
Derek Parnell wrote:Indeed. That kicks ass. I still have to completely wrap my head around that function literal syntax. All of the sudden it is very useful to me. :)I'm thinking incase someone wanted to say, have a mouse handling function be triggered by the GUI's delegate and also have it artificially triggered by some other code via a direct function call (maybe a tutorial, debug routine, or something like that).Sure you can! How about this ... import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } int incr( int a ) { return a + 1; } static this() { increment = delegate int ( int a ) {return incr(a); }; } Would that do?
Jun 20 2006
Derek Parnell escribió:On Wed, 21 Jun 2006 02:12:54 -0400, Chad J wrote:I thought the frame pointer would get lost and cause a segfault later on (see DFL events handling for an example.) Did that change with 0.161?Pretty nice, but then I can't do something like this:....writefln( increment(1) ); writefln( incr(2) );....I'm thinking incase someone wanted to say, have a mouse handling function be triggered by the GUI's delegate and also have it artificially triggered by some other code via a direct function call (maybe a tutorial, debug routine, or something like that).Sure you can! How about this ... import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } int incr( int a ) { return a + 1; } static this() { increment = delegate int ( int a ) {return incr(a); }; } Would that do?-- Carlos Santander BernalI suppose they should just call the delegate though. I like it. Thanks.Yeah, I guess you could do that as well.
Jun 21 2006
Carlos Santander wrote:Derek Parnell escribió:The frame pointer becomes invalid, but that is no problem since the delegate is function-like and does not access the frame context (i.e., it's not a closure). -- Bruno Medeiros - CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#DSure you can! How about this ... import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } int incr( int a ) { return a + 1; } static this() { increment = delegate int ( int a ) {return incr(a); }; } Would that do?I thought the frame pointer would get lost and cause a segfault later on (see DFL events handling for an example.) Did that change with 0.161?
Jul 18 2006
Bruno Medeiros escribió:Carlos Santander wrote:In this case, yes, you're right. I must admit I didn't notice that. However, in other circumstances (more complex, I'd say) it's a valid point to take into account. -- Carlos Santander BernalDerek Parnell escribió:The frame pointer becomes invalid, but that is no problem since the delegate is function-like and does not access the frame context (i.e., it's not a closure).Sure you can! How about this ... import std.stdio; int delegate(int) increment; void main() { writefln( increment(1) ); writefln( incr(2) ); } int incr( int a ) { return a + 1; } static this() { increment = delegate int ( int a ) {return incr(a); }; } Would that do?I thought the frame pointer would get lost and cause a segfault later on (see DFL events handling for an example.) Did that change with 0.161?
Jul 21 2006
Chad J wrote:So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates? I suppose I could choose one or the other, but I think it desirable to allow use of both since I don't want to force the user of the library into a particular style or make them use ugly workarounds. I am currently thinking of a few possible solutions, none of which look very pleasing to me:I'd pick delegates.programming. Example -At the moment, a function can't be cast to a delegate, but I think this will change in the future (since it's theoretically possible). In the mean time you can use the new lambda/literal syntax: int module_level_func() { return 1; } void somefunc( int delegate() callback ) { callback(); } void main() { // somefunc( &module_level_func );// not (yet) possible somefunc( { return module_level_func();} ); //wrap it } L.
Jun 21 2006
Chad J wrote:So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates?[...] a while back someone found out that you can take a delegate and replace the internal function pointer with a regular function pointer and it still works just fine. Given this, you could wright a little function*-to-delegate function and let people do this UseThisCallback(int delegate(int)); int delegate(int) f2d(int function(int) fnp){...} int fn(int); void main() { UseThisCallback(f2d(&fn)); } I known this is an *ugly* hack, OTOH maybe Walter can be convinced to add a function-pointer to delegate cast that does this in a consistent manner. cast(int delegate(int))&fn
Jun 21 2006
BCS wrote:Chad J wrote:maybe just "cast(delegate)&fn" in the spirit of inferred typing? --So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates?[...] a while back someone found out that you can take a delegate and replace the internal function pointer with a regular function pointer and it still works just fine. Given this, you could wright a little function*-to-delegate function and let people do this UseThisCallback(int delegate(int)); int delegate(int) f2d(int function(int) fnp){...} int fn(int); void main() { UseThisCallback(f2d(&fn)); } I known this is an ugly hack, OTOH maybe Walter can be convinced to add a function-pointer to delegate cast that does this in a consistent manner. cast(int delegate(int))&fn
Jul 18 2006
Andrei Khropov wrote:BCS wrote:[...]a while back someone found out that you can take a delegate and replace the internal function pointer with a regular function pointer and it still works just fine. Given this, you could wright a little function*-to-delegate function and let people do thisThat /would/ be better.I known this is an ugly hack, OTOH maybe Walter can be convinced to add a function-pointer to delegate cast that does this in a consistent manner. cast(int delegate(int))&fnmaybe just "cast(delegate)&fn" in the spirit of inferred typing?
Jul 18 2006
BCS wrote:Chad J wrote:It works fine *most of the time*. IIRC, sometimes it will result in incorrect code. We could deal with those cases if we knew the exact circumstances under which function parameters are passed in registers. But until the ABI gets formalised, it's a non-portable hack that occasionally fails.So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates?[...] a while back someone found out that you can take a delegate and replace the internal function pointer with a regular function pointer and it still works just fine.
Jul 19 2006
Don Clugston wrote:BCS wrote:I wouldn't use it (if possible) even if it was portable. The compiler should do this for you. cast(delegate)fnpt;Chad J wrote:It works fine *most of the time*. IIRC, sometimes it will result in incorrect code. We could deal with those cases if we knew the exact circumstances under which function parameters are passed in registers. But until the ABI gets formalised, it's a non-portable hack that occasionally fails.So I have decided to roll my own GUI library, one dedicated to computer games. But I've run into a bit of an unpleasant design problem - for handling callbacks, how should my library expose function pointers and delegates?[...] a while back someone found out that you can take a delegate and replace the internal function pointer with a regular function pointer and it still works just fine.
Jul 25 2006