Anonymous Delegates

Russell Lewis webmaster at villagersonline.com
Mon Jun 16 07:25:27 PDT 2008


Erik Lechak wrote:
> I though maybe I could do this:
> b.addOnClicked( delegate void(Button aux){ 
>     this.doSomethingAButtonCanDo(); 
> } );

Not having used gtk much, I'll assume that the Button object passed to 
the callback is the same button as the variable 'b' in your attempt 
above.  So if you want 'b' to call doSomethingAButtonCanDo() when it is 
clicked, then you could write:

BEGIN CODE
   b.addOnClicked(
       delegate void(Button ignored)
       {
         b.doSomethingAButtonCanDo();
       });
END CODE

or, since the argument is the same button, this also works:

BEGIN CODE
   b.addOnClicked(
       delegate void(Button aux)
       {
         aux.doSomethingAButtonCanDo();
       });
END CODE


This still seems a little bit useless.  But as you get more advanced, 
whole new worlds open up.  Let's look at how we might change the gtk API 
to be more delegate-aware.  Since a delegate can carry with it some 
context, we could remove the Button argument from the callback:

BEGIN CODE
    b.addOnClicked_noArg( &b.doSomethingAButtonCanDo );
END CODE

Notice that the syntax above constructs a delegate with 'b' as the 
'this' pointer, and 'doSomethingAButtonCanDo' as the function.

The cool thing, of course, is that you can pass delegates which point to 
any other type of object, so long as the delegate takes no arguments. 
For instance:

BEGIN CODE
    SomeWindowClass w = GetSomeSpecificWindow();
    b.addOnClicked_noArg( &w.closeWindow );
END CODE

Now you see that (in D2, which has full and automatic closure support), 
an anonymous delegate is just another cool thing that can be passed:

BEGIN CODE
    SomeInterestingValue v = <whatever>;
    SomeWindowClass w = GetSomeSpecificWindow();
    b.addOnClicked_noArg({ w.setSomeProperty(v) });
END CODE

Note that in the above example, the 'this' pointer will point to the 
automatically-allocated heap frame, which will store your 'v' and 'w' 
variables, and when the delegate is called, that one-line function will 
be executed.


In my experience, the more that I port my code (and my callbacks) to use 
delegates, the more amazing things get.  It's sometimes hard to see why 
they are so important in trivial examples...but imagine that you were 
carrying around a few dozen local variables.  Then delegates (and 
closures in particular) get *really* nice.

BEGIN CODE
    void myFunction(<some arguments>)
    {
       <set some variables>

       CallLibraryFunction(
          delegate void(<some more arguments>)
          {
             <do something nontrivial which includes all the args & vars 
above>
          });
    }
END CODE



More information about the Digitalmars-d mailing list