Jump to page: 1 2
Thread overview
Library writing - delegates or fp's?
Jun 21, 2006
Chad J
Jun 21, 2006
Derek Parnell
Jun 21, 2006
Chad J
Jun 21, 2006
Derek Parnell
Jun 21, 2006
Chad J
Jun 21, 2006
Carlos Santander
Jul 18, 2006
Bruno Medeiros
Jul 21, 2006
Carlos Santander
Jun 21, 2006
Lionello Lunesu
Jun 21, 2006
BCS
Jul 18, 2006
Andrei Khropov
Jul 18, 2006
BCS
Jul 20, 2006
Don Clugston
Jul 25, 2006
BCS
June 21, 2006
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:

#1:  Force them to use delegates and work around it to do module-level 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);
    }
}

#2:  Provide a templated struct kind of thing that can double as 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;
    }
}

#3:  Expose both function pointers and delegates, with some kind of 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 :)
June 21, 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:
> 
> #1:  Force them to use delegates and work around it to do module-level 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
June 21, 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.
June 21, 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
June 21, 2006
Derek Parnell wrote:
> 
>>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?
>  

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.  :)
June 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.

> #1:  Force them to use delegates and work around it to do module-level 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.
June 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
June 21, 2006
Derek Parnell escribió:
> 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 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?

>> I suppose they should just call the delegate though.  I like it.  Thanks.
> 
> Yeah, I guess you could do that as well.
> 


-- 
Carlos Santander Bernal
July 18, 2006
Carlos Santander wrote:
> Derek Parnell escribió:
>> 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?
> 

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#D
July 18, 2006
BCS wrote:

> 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

maybe just "cast(delegate)&fn" in the spirit of inferred typing?


-- 

« First   ‹ Prev
1 2