digitalmars.D - Newbie initial comments on D language - delegate
- Edward Diener (35/35) Jan 28 2008 As I was reading about delegates and the syntax to initialize them I was
- Walter Bright (4/12) Jan 28 2008 To merge the two requires the generation of thunks at runtime to
- Lionello Lunesu (5/18) Jan 29 2008 Perhaps allowing a delegate to point to a free function is enough to
- Walter Bright (3/12) Jan 29 2008 Me too, but it still changes the calling convention, and still needs a
- Craig Black (12/24) Jan 29 2008 I don't understand why this is so difficult. There already exists a
- Edward Diener (19/38) Jan 29 2008 Yes, that is the essence of my suggestion.
- Leandro Lucarella (10/21) Jan 29 2008 And please, don't forget we need plain function pointers to interact wit...
- Walter Bright (4/20) Jan 29 2008 Yes, we do need that. But plain function pointers seem to get more and
- Edward Diener (5/19) Jan 29 2008 You might need plain function pointers but you do not need 'function'. A...
- Janice Caron (8/12) Jan 29 2008 In general, the compiler cannot tell at compile time whether or a not
- Don Clugston (7/22) Jan 30 2008 But we still need typedefs and declarations. How do you declare
- Janice Caron (4/7) Jan 30 2008 The old fashioned way?
- Leandro Lucarella (10/17) Jan 30 2008 That's that the keyword function is for. What's the point of removing it
- Janice Caron (3/8) Jan 30 2008 Or, for any delegate dg,
- Don Clugston (6/16) Jan 30 2008 That only works if you can have extern(C), extern(Windows) delegates.
- Janice Caron (10/12) Jan 30 2008 Yes, that is precisely my suggestion. I see that as an advantage, not
- Joel C. Salomon (15/24) Jan 30 2008 -----BEGIN PGP SIGNED MESSAGE-----
- Frits van Bommel (5/12) Jan 30 2008 How about when you're interfacing with a different language and are
- Don Clugston (10/26) Jan 30 2008 Ah, OK -- that's a reasonable argument. Certainly it does seem that 'fun...
- Edward Diener (5/14) Jan 30 2008 But it can generate code which checks at run-time if this is the case
- Janice Caron (7/11) Jan 30 2008 Good point.
- Sean Kelly (6/19) Jan 30 2008 Can't say I've thought this through, but what if delegates simply worked
- BCS (5/22) Jan 28 2008 The issue I see is that delegates are 64 bits (assuming a 32bit system) ...
- Russell Lewis (20/60) Jan 28 2008 I agree with the sentiment that it should be possible to implicitly cast...
- BCS (21/24) Jan 28 2008 somthing like this?
- Russell Lewis (15/48) Jan 29 2008 Yeah, I've seen people use the union magic to make it work without a
- Jarrett Billingsley (5/19) Jan 29 2008 For those who aren't aware, this will only work in D2, not D1. In D1 yo...
As I was reading about delegates and the syntax to initialize them I was thinking that such similar natural syntax had been suggested to C++ many times over the years. Of course delegates already have their antecedents in C++ Builder closures and .Net delegates among others. My reaction to delegates and their elegant syntax was "bravo, of course" but I also had the reaction of why are there both 'delegate' and 'function'. Later in the pdf documentation I saw the a note that the future might see 'delegate' and 'function' folded into a single callable type. My reaction to this is: ABSOLUTELY NECESSARY. In fact I think it is a mistake to have divided callables into two types. The 'function' should have been dropped and a 'delegate' should have been initializable from any sort of callable in D, including class member function, class non-member functions ( static member functions ), global functions, nested functions, and any other callable in D I might have missed. This is what C++ currently achieves through boost::function/boost::bind and it would be remarkable if D did not achieve the same sort of interoperability. Making a delegate be able to represent any callable type of the given parameters/return-type enables any function-like object to be treated as a first-class language construct in D. Having two distinct callable types simply bifurcates the effectiveness of this concept. Needless to say, implementing callbacks, as well as events ( signals/slots ) having to deal with two different callable types whereas one would do nicely, is not the best design for a language. A callback in general does not care whether the handler is a member function, global function, or any other type of callable, it just makes the call and lets the callback handler ( "functor" if you will ) do what it wants with it. Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.
Jan 28 2008
Edward Diener wrote:Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 28 2008
Walter Bright wrote:Edward Diener wrote:Perhaps allowing a delegate to point to a free function is enough to make people happy? It sure would please me ;) L.Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 29 2008
Lionello Lunesu wrote:Walter Bright wrote:Me too, but it still changes the calling convention, and still needs a thunk.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.Perhaps allowing a delegate to point to a free function is enough to make people happy? It sure would please me ;)
Jan 29 2008
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:fnmrjo$109m$1 digitalmars.com...Lionello Lunesu wrote:I don't understand why this is so difficult. There already exists a function template that can be used to convert a function pointer to a delegate. BCS showed it to me a while back. Why not just have DMD call such a function to convert function pointers to delegates? T delegate(A) Fn2Dg(T, A...)(T function(A) f) { struct tmp { T ret(A args){ return (cast(T function(A))this)(args); } }; return &(cast(tmp*)f).ret; } -CraigWalter Bright wrote:Me too, but it still changes the calling convention, and still needs a thunk.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.Perhaps allowing a delegate to point to a free function is enough to make people happy? It sure would please me ;)
Jan 29 2008
Lionello Lunesu wrote:Walter Bright wrote:Yes, that is the essence of my suggestion. There is no need to have a separate 'function' as callback since a 'delegate' should be able to encompass any non-member function also. After all if a 'delegate' needs both an object pointer and and a ( member ) function pointer, and a 'function' just needs a function pointer, then for a delegate encompassing a free function the object pointer is just null. As I originally stated, setting up a callback does NOT care whether what is called is a member function or a non-member function, any more than an event ( a signal ) cares whether event handlers ( slots ) are member functions or free functions. Furthermore, with both 'function' and 'delegate' representing callables, setting up a callback, or an event, means having to cater to two different types of callables. This just complicates what should be a single concept and implementation. I am sure Walter understands all this and the difficulty in having a single callback has nothing to do with the validity of the idea and everything to do with the implementation. Yet clearly it is a much superior design to the separate 'function'/'delegate' dichotomy.Edward Diener wrote:Perhaps allowing a delegate to point to a free function is enough to make people happy? It sure would please me ;)Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 29 2008
Walter Bright, el 28 de enero a las 18:51 me escribiste:Edward Diener wrote:And please, don't forget we need plain function pointers to interact with C. -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Todos en el mundo somos grasas, no hago distinción de sexo y raza, sólo que algunos lo disfrutan y otros no pueden evitarlo.Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 29 2008
Leandro Lucarella wrote:Walter Bright, el 28 de enero a las 18:51 me escribiste:Yes, we do need that. But plain function pointers seem to get more and more relegated to only being for that, much as char* pointers have given way to char[], and you only see char* when interfacing with C.Edward Diener wrote:And please, don't forget we need plain function pointers to interact with C.Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 29 2008
Leandro Lucarella wrote:Walter Bright, el 28 de enero a las 18:51 me escribiste:You might need plain function pointers but you do not need 'function'. A 'delegate' which encompassed a 'function', with the object pointer part of the delegate being null in that particle case, should be implicitly convertible to a C function pointer.Edward Diener wrote:And please, don't forget we need plain function pointers to interact with C.Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 29 2008
On 1/30/08, Edward Diener <eddielee_no_spam_here tropicsoft.com> wrote:You might need plain function pointers but you do not need 'function'. A 'delegate' which encompassed a 'function', with the object pointer part of the delegate being null in that particle case, should be implicitly convertible to a C function pointer.In general, the compiler cannot tell at compile time whether or a not a value is null at runtime (though in an expression like &f it obviously can), so I don't think it can be quite that automatic. Nonetheless, I'm inclined to agree that we probably don't need the "function" keyword at all. delegate f; oldFashionedCFunction( f.funcptr );
Jan 29 2008
Janice Caron wrote:On 1/30/08, Edward Diener <eddielee_no_spam_here tropicsoft.com> wrote:But we still need typedefs and declarations. How do you declare oldFashionedCFunction() ? At the moment, you can have an extern(C) function pointer, ... but what is an extern(C) delegate ? AFAIK, all delegates use the D calling convention. This is not true for functions. Clearly several things would need to change.You might need plain function pointers but you do not need 'function'. A 'delegate' which encompassed a 'function', with the object pointer part of the delegate being null in that particle case, should be implicitly convertible to a C function pointer.In general, the compiler cannot tell at compile time whether or a not a value is null at runtime (though in an expression like &f it obviously can), so I don't think it can be quite that automatic. Nonetheless, I'm inclined to agree that we probably don't need the "function" keyword at all. delegate f; oldFashionedCFunction( f.funcptr );
Jan 30 2008
On Jan 30, 2008 8:16 AM, Don Clugston <dac nospam.com.au> wrote:How do you declare oldFashionedCFunction() ?The old fashioned way? extern(C) void (*callback)(int,int);what is an extern(C) delegate ?How can that even make sense? C does not have delegates.
Jan 30 2008
Janice Caron, el 30 de enero a las 08:36 me escribiste:On Jan 30, 2008 8:16 AM, Don Clugston <dac nospam.com.au> wrote:That's that the keyword function is for. What's the point of removing it if we need it? -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- "CIRILO" Y "SIRACUSA" DE "SEÑORITA MAESTRA": UNO MUERTO Y OTRO PRESO -- Crónica TVHow do you declare oldFashionedCFunction() ?The old fashioned way? extern(C) void (*callback)(int,int);
Jan 30 2008
On Jan 30, 2008 8:36 AM, Janice Caron <caron800 googlemail.com> wrote:On Jan 30, 2008 8:16 AM, Don Clugston <dac nospam.com.au> wrote:Or, for any delegate dg, typeof(dg.funcptr) callback;How do you declare oldFashionedCFunction() ?The old fashioned way? extern(C) void (*callback)(int,int);
Jan 30 2008
Janice Caron wrote:On Jan 30, 2008 8:36 AM, Janice Caron <caron800 googlemail.com> wrote:That's just 'function', using the hideous C syntax.On Jan 30, 2008 8:16 AM, Don Clugston <dac nospam.com.au> wrote:How do you declare oldFashionedCFunction() ?The old fashioned way? extern(C) void (*callback)(int,int);Or, for any delegate dg, typeof(dg.funcptr) callback;That only works if you can have extern(C), extern(Windows) delegates. The problem is that, because of calling conventions, not all function pointers can be expressed by dg.funcptr. The existing delegates are therefore not a superset of function pointers.
Jan 30 2008
On Jan 30, 2008 11:17 AM, Don Clugston <dac nospam.com.au> wrote:Yes, that is precisely my suggestion. I see that as an advantage, not a disadvantage, because it would encourage people to use "delegate", unless they absolutely couldn't. All I'm saying is, if you're working in D alone, you can get along just fine using "delegate" instead of "function", and therefore the keyword "function" is unnecessary. On the other hand, if you want to interface with C, then you shouldn't be surprised if you have to use hideous C syntax. So we /could/ ditch "function" and have one fewer keyword.That's just 'function', using the hideous C syntax.extern(C) void (*callback)(int,int);
Jan 30 2008
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Janice Caron wrote:On Jan 30, 2008 11:17 AM, Don Clugston <dac nospam.com.au> wrote:<snip>Yes, that is precisely my suggestion. I see that as an advantage, not a disadvantage, because it would encourage people to use "delegate", unless they absolutely couldn't.That's just 'function', using the hideous C syntax.extern(C) void (*callback)(int,int);On the other hand, if you want to interface with C, then you shouldn't be surprised if you have to use hideous C syntax.I’d go a step further: If you’re interfacing to a C function, you presumably have its declaration handy -- in C syntax. Why have a keyword that’s only useful in the one circumstance where it’s not needed? - --Joel -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.6 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFHoKpPzLx4GzBL9dYRArmAAKDP1DkAj5w6CAaoPHttIXaevdFLygCgkNF6 aSjVbilEUnDyoiSr4lbn6xw= =yN2s -----END PGP SIGNATURE-----
Jan 30 2008
Joel C. Salomon wrote:Janice Caron wrote:How about when you're interfacing with a different language and are using the C calling convention as a 'lingua franca'? (Or even linking DMD-compiled code and GDC-compiled code, since they use different calling conventions for D functions)On the other hand, if you want to interface with C, then you shouldn't be surprised if you have to use hideous C syntax.I’d go a step further: If you’re interfacing to a C function, you presumably have its declaration handy -- in C syntax. Why have a keyword that’s only useful in the one circumstance where it’s not needed?
Jan 30 2008
Janice Caron wrote:On Jan 30, 2008 11:17 AM, Don Clugston <dac nospam.com.au> wrote:Ah, OK -- that's a reasonable argument. Certainly it does seem that 'function' is becoming a 'foreign' concept to D; you almost always want to use 'delegate' instead. Note (1) 'function' has a different meaning inside is() expressions. alias void function(int,int) Foo; static assert (is(Foo == function)); // fails! Note (2) function pointers do pop up in other places even if you program exclusively in D, for example in reflection (compile time and runtime). The vtable is full of function pointers, not delegates.Yes, that is precisely my suggestion. I see that as an advantage, not a disadvantage, because it would encourage people to use "delegate", unless they absolutely couldn't. All I'm saying is, if you're working in D alone, you can get along just fine using "delegate" instead of "function", and therefore the keyword "function" is unnecessary. On the other hand, if you want to interface with C, then you shouldn't be surprised if you have to use hideous C syntax. So we /could/ ditch "function" and have one fewer keyword.That's just 'function', using the hideous C syntax.extern(C) void (*callback)(int,int);
Jan 30 2008
Janice Caron wrote:On 1/30/08, Edward Diener <eddielee_no_spam_here tropicsoft.com> wrote:But it can generate code which checks at run-time if this is the case and takes the correct action. In the case of converting a delegate which has a non-null value as the object pointer, the code generated if one tries to cast it to a plain C function pointer could throw an exception.You might need plain function pointers but you do not need 'function'. A 'delegate' which encompassed a 'function', with the object pointer part of the delegate being null in that particle case, should be implicitly convertible to a C function pointer.In general, the compiler cannot tell at compile time whether or a not a value is null at runtime (though in an expression like &f it obviously can), so I don't think it can be quite that automatic.
Jan 30 2008
On Jan 30, 2008 11:24 PM, Edward Diener <eddielee_no_spam_here tropicsoft.com> wrote:But it can generate code which checks at run-time if this is the case and takes the correct action. In the case of converting a delegate which has a non-null value as the object pointer, the code generated if one tries to cast it to a plain C function pointer could throw an exception.Good point. Along similar lines, the compiler could generate code which checks for null dereferences, but I don't see that happening anytime soon. :-( These are exactly the sort of things that ought to be in debug (but not release) builds (IMO).
Jan 30 2008
Walter Bright wrote:Edward Diener wrote:Can't say I've thought this through, but what if delegates simply worked for all functions with the extern (D) calling convention, regardless of scope? That would cover the vast majority of cases, and make other calling conventions somewhat of a special case, which they are anyway. SeanPerhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.To merge the two requires the generation of thunks at runtime to manipulate the parameters and calling convention. It's doable, but not simple.
Jan 30 2008
Reply to Edward,As I was reading about delegates and the syntax to initialize them I was thinking that such similar natural syntax had been suggested to C++ many times over the years. Of course delegates already have their antecedents in C++ Builder closures and .Net delegates among others. My reaction to delegates and their elegant syntax was "bravo, of course" but I also had the reaction of why are there both 'delegate' and 'function'. Later in the pdf documentation I saw the a note that the future might see 'delegate' and 'function' folded into a single callable type. My reaction to this is: ABSOLUTELY NECESSARY. In fact I think it is a mistake to have divided callables into two types. The 'function' should have been dropped and a 'delegate' should have been initializable from any sort of callable in D, including class member function, class non-member functions ( static member functions ), global functions, nested functions, and any other callable in D I might have missed.The issue I see is that delegates are 64 bits (assuming a 32bit system) and functions are 32 bits. To maintain link compatibility with C, the 32bit plain-old-function-pointer form is needed. But it can't (cleanly) be used with delegates that need that extra 32bits for the context/this pointer.
Jan 28 2008
I agree with the sentiment that it should be possible to implicitly cast a function to a delegate, but I don't think that merging the two is the best idea. First, in my experience with D, I find that function pointers are rather rare. As you get to use D more and more, you end up using delegate literals (or delegates to member functions) more and more, while pointers to ordinary functions become rare. Sure, I just had to handle function pointers a few days ago, but that was noteworthy as the first time I had had to use them in a long time. And what I did was just generate a template which automatically created a delegate out of it. :) So, IMHO, having both doesn't add too much complexity to code, particularly if the implicit cast thing works some day. The reason that I think that they should be retained (in addition to the C interop argument already posted) is that D aims to be a language that allows you to go down to the bare metal and write "C code in D." If we had only delegates, and not function pointers, then we are hamstringing somebody who wants to write a bare-metal, fast-as-possible D program. For me, with my toy programs, I'll keep using delegates for just about everything. :) Edward Diener wrote:As I was reading about delegates and the syntax to initialize them I was thinking that such similar natural syntax had been suggested to C++ many times over the years. Of course delegates already have their antecedents in C++ Builder closures and .Net delegates among others. My reaction to delegates and their elegant syntax was "bravo, of course" but I also had the reaction of why are there both 'delegate' and 'function'. Later in the pdf documentation I saw the a note that the future might see 'delegate' and 'function' folded into a single callable type. My reaction to this is: ABSOLUTELY NECESSARY. In fact I think it is a mistake to have divided callables into two types. The 'function' should have been dropped and a 'delegate' should have been initializable from any sort of callable in D, including class member function, class non-member functions ( static member functions ), global functions, nested functions, and any other callable in D I might have missed. This is what C++ currently achieves through boost::function/boost::bind and it would be remarkable if D did not achieve the same sort of interoperability. Making a delegate be able to represent any callable type of the given parameters/return-type enables any function-like object to be treated as a first-class language construct in D. Having two distinct callable types simply bifurcates the effectiveness of this concept. Needless to say, implementing callbacks, as well as events ( signals/slots ) having to deal with two different callable types whereas one would do nicely, is not the best design for a language. A callback in general does not care whether the handler is a member function, global function, or any other type of callable, it just makes the call and lets the callback handler ( "functor" if you will ) do what it wants with it. Perhaps there are some implementation issues regarding this which I do not understand but these should be overcome in order to present a single interface to the callable concept. Perhaps this has been discussed ad nauseam on this NG already, so please correct me if I do not understand all the ramifications of uniting all callable types under the single idea of 'delegate' while perhaps keeping 'function' around merely for backward compatibility with old code until eventually it is dropped.
Jan 28 2008
Reply to Russell,what I did was just generate a template which automatically created a delegate out of it.somthing like this? // IFTI might want somthing else\ here R delegate(A) convert(R, A...)(R function(A) fnp) { struct S { // "this" is a function pointer not a S* R do(A a) { U u; u.s = this; retrun s.f(a);} } union U { S* s; R function(a) f; } U u; u.f= fnp; retrun &u.s.do; } note it never news anything! *Untested, but I've used the idea befor.*
Jan 28 2008
Yeah, I've seen people use the union magic to make it work without a new. It's a cool trick, but it makes me squirm when I think about portability. So I use a general version, using closures (note that my template uses a fixed "void" return code...previous posts in the NG can show you how to IFTI non-void return codes): void delegate(TPL) convert(TPL...)(void function(TPL) func) { return delegate void(TPL args) { func(args); }; } // note that 'func' is put on the heap automatically by the closure // mechanism in the compiler. BCS wrote:Reply to Russell,what I did was just generate a template which automatically created a delegate out of it.somthing like this? // IFTI might want somthing else\ here R delegate(A) convert(R, A...)(R function(A) fnp) { struct S { // "this" is a function pointer not a S* R do(A a) { U u; u.s = this; retrun s.f(a);} } union U { S* s; R function(a) f; } U u; u.f= fnp; retrun &u.s.do; } note it never news anything! *Untested, but I've used the idea befor.*
Jan 29 2008
"Russell Lewis" <webmaster villagersonline.com> wrote in message news:fnnivs$11k$1 digitalmars.com...Yeah, I've seen people use the union magic to make it work without a new. It's a cool trick, but it makes me squirm when I think about portability. So I use a general version, using closures (note that my template uses a fixed "void" return code...previous posts in the NG can show you how to IFTI non-void return codes): void delegate(TPL) convert(TPL...)(void function(TPL) func) { return delegate void(TPL args) { func(args); }; } // note that 'func' is put on the heap automatically by the closure // mechanism in the compiler.For those who aren't aware, this will only work in D2, not D1. In D1 you'll probably get an access violation upon attempting to call the returned delegate.
Jan 29 2008