February 10, 2011 Re: Template for function or delegate (nothing else) | ||||
---|---|---|---|---|
| ||||
Posted in reply to useo | On Thu, 10 Feb 2011 09:48:14 -0500, useo <useo@start.bg> wrote: > I created a complete, new file with the following code: > > module example; > > void main(string[] args) { > Example!(void function()) myVar; > } > > class Example(T) if (is(T == delegate) || is(T == function)) { > } > > And what I get is: > > example.d(4): Error: template instance Example!(void function()) does > not match template declaration Example(T) if (is(T == delegate) || is > (T == function)) > example.d(4): Error: Example!(void function()) is used as a type > > I'm using the current stable version 2.051. Found this invalid bug. Apparently, this is expected (!) behavior: http://d.puremagic.com/issues/show_bug.cgi?id=3464 So use this instead: class Example(T) if (is(T == delegate) || is(typeof(*T.init) == function)) Ugly, I know, but I guess that's what we got to work with. -Steve |
February 10, 2011 Re: Template for function or delegate (nothing else) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | == Auszug aus Steven Schveighoffer (schveiguy@yahoo.com)'s Artikel > On Thu, 10 Feb 2011 09:48:14 -0500, useo <useo@start.bg> wrote: > > I created a complete, new file with the following code: > > > > module example; > > > > void main(string[] args) { > > Example!(void function()) myVar; > > } > > > > class Example(T) if (is(T == delegate) || is(T == function)) { > > } > > > > And what I get is: > > > > example.d(4): Error: template instance Example!(void function()) does > > not match template declaration Example(T) if (is(T == delegate) || is > > (T == function)) > > example.d(4): Error: Example!(void function()) is used as a type > > > > I'm using the current stable version 2.051. > Found this invalid bug. Apparently, this is expected (!) behavior: > http://d.puremagic.com/issues/show_bug.cgi?id=3464 > So use this instead: > class Example(T) if (is(T == delegate) || is(typeof(*T.init) == function)) > Ugly, I know, but I guess that's what we got to work with. -Steve Yes, looks a bit unusual but it works, thanks! |
February 10, 2011 Re: Template for function or delegate (nothing else) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 02/10/2011 02:51 PM, Steven Schveighoffer wrote: > On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir@gmail.com> wrote: > >> On 02/09/2011 11:05 PM, Steven Schveighoffer wrote: > >>> I don't think you want templates. What you want is a tagged union (and a struct >>> is MUCH better suited for this): >>> >>> // untested! >>> >>> struct Example >>> { >>> private >>> { >>> bool isDelegate; >>> union >>> { >>> void function() fn; >>> void delegate() dg; >>> } >>> } >>> >>> void setCallback(void function() f) { this.fn = f; isDelegate = false;} >>> void setCallback(void delegate() d) { this.dg = d; isDelegate = true;} >>> >>> void opCall() >>> { >>> if(isDelegate) >>> dg(); >>> else >>> fn(); >>> } >>> } >> >> Waow, very nice solution. >> I really question the function/delegate distinction (mostly artificial, imo) >> that "invents" issues necessiting workarounds like that. What does it mean, >> what does it bring? > > A function pointer is compatible with a C function pointer. C does not have > delegates, so if you want to do callbacks, you need to use function pointers. > There is no way to combine them and keep C compatibility. > >> Right, there is one pointer less for funcs. This save 4 or 8 bytes, so to >> say, nothing; who develops apps with arrays of billions of funcs? There are >> written in source ;-) Even then, if this saving of apointer was of any >> relevance, then it should be an implementation detail that does not leak into >> artificial semantic diff, creating issues on the programmer side. What do you >> think? > > What you want is already implemented. There is a relatively new phobos > construct that builds a delegate out of a function pointer. In fact, my code > could use it and save the tag: > > > // again, untested! > > import std.functional : toDelegate; > > struct Example > { > private void delegate() dg; > > void setCallback(void function() f) { this.dg = toDelegate(f); } > void setCallback(void delegate() d) { this.dg = d; } > > void opCall() { dg(); } > } > > Note that toDelegate doesn't appear on the docs because of a doc generation bug... Right. I had not thought at the C-compatibility issue. So, let us say the func/dg distinction must remain in the language, on programmer-side, because of that. Then, is there anything that prevent the above cast to be implicit? Then, programmers would only have to define a single interface, using delegate everywhere; and not care about where and how user funcs are defined. (because as you know presently whether a ref'ed func becomes a func pointer or a delegate depends on /where/ it is defined...) Second point. I would like referencing of functions/delegates passed as arguments to be implicite. After all, conceptually, what we pass is a "function object". Not a pointer. That the implementation needs to "point" them is just this, implementation. The '&' just pollutes the code meaninglessly; and it's absence creates weird bugs: void f0 ( ) { writeln(1); } void f1 (int i) { writeln(i); } void do0 (void function ( ) f) { f( ); } void do1 (void function (int) f) { f(3); } unittest { // Error: function __trials__.do0 (void function() f) is not callable // using argument types (void) do0(f0); // __trials__.d(46): Error: function __trials__.f1 (int i) is not callable // using argument types () do1(f1); do0(&f0); // ok do1(&f1); // ok } Error messages are difficult to interpret for a diagnosis, I guess. Note that the first one concerns the caller, while the second one concerns the callee... Implicite referencing would solve that issue /and/ match semantics /and/ be more consistent /and/ make code nicer. About consistency, I mean that functions are already implicitely dereferenced: do1 does not need to call its arg f using (*f)(3); (this version works as well, indeed) denis -- _________________ vita es estrany spir.wikidot.com |
February 10, 2011 Re: Template for function or delegate (nothing else) | ||||
---|---|---|---|---|
| ||||
Posted in reply to spir | On Thu, 10 Feb 2011 12:04:28 -0500, spir <denis.spir@gmail.com> wrote: > On 02/10/2011 02:51 PM, Steven Schveighoffer wrote: >> On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir@gmail.com> wrote: >> >>> On 02/09/2011 11:05 PM, Steven Schveighoffer wrote: >> >>>> I don't think you want templates. What you want is a tagged union (and a struct >>>> is MUCH better suited for this): >>>> >>>> // untested! >>>> >>>> struct Example >>>> { >>>> private >>>> { >>>> bool isDelegate; >>>> union >>>> { >>>> void function() fn; >>>> void delegate() dg; >>>> } >>>> } >>>> >>>> void setCallback(void function() f) { this.fn = f; isDelegate = false;} >>>> void setCallback(void delegate() d) { this.dg = d; isDelegate = true;} >>>> >>>> void opCall() >>>> { >>>> if(isDelegate) >>>> dg(); >>>> else >>>> fn(); >>>> } >>>> } >>> >>> Waow, very nice solution. >>> I really question the function/delegate distinction (mostly artificial, imo) >>> that "invents" issues necessiting workarounds like that. What does it mean, >>> what does it bring? >> >> A function pointer is compatible with a C function pointer. C does not have >> delegates, so if you want to do callbacks, you need to use function pointers. >> There is no way to combine them and keep C compatibility. >> >>> Right, there is one pointer less for funcs. This save 4 or 8 bytes, so to >>> say, nothing; who develops apps with arrays of billions of funcs? There are >>> written in source ;-) Even then, if this saving of apointer was of any >>> relevance, then it should be an implementation detail that does not leak into >>> artificial semantic diff, creating issues on the programmer side. What do you >>> think? >> >> What you want is already implemented. There is a relatively new phobos >> construct that builds a delegate out of a function pointer. In fact, my code >> could use it and save the tag: >> >> >> // again, untested! >> >> import std.functional : toDelegate; >> >> struct Example >> { >> private void delegate() dg; >> >> void setCallback(void function() f) { this.dg = toDelegate(f); } >> void setCallback(void delegate() d) { this.dg = d; } >> >> void opCall() { dg(); } >> } >> >> Note that toDelegate doesn't appear on the docs because of a doc generation bug... > > Right. > > I had not thought at the C-compatibility issue. So, let us say the func/dg distinction must remain in the language, on programmer-side, because of that. Then, is there anything that prevent the above cast to be implicit? Then, programmers would only have to define a single interface, using delegate everywhere; and not care about where and how user funcs are defined. > (because as you know presently whether a ref'ed func becomes a func pointer or a delegate depends on /where/ it is defined...) > > Second point. I would like referencing of functions/delegates passed as arguments to be implicite. After all, conceptually, what we pass is a "function object". Not a pointer. That the implementation needs to "point" them is just this, implementation. The '&' just pollutes the code meaninglessly; This is the way it is in C, and D purposely does not do this to avoid ambiguity (did you want to call the function or get it's address?). > and it's absence creates weird bugs: > > void f0 ( ) { writeln(1); } > void f1 (int i) { writeln(i); } > void do0 (void function ( ) f) { f( ); } > void do1 (void function (int) f) { f(3); } > > unittest { > // Error: function __trials__.do0 (void function() f) is not callable > // using argument types (void) > do0(f0); > > // __trials__.d(46): Error: function __trials__.f1 (int i) is not callable > // using argument types () > do1(f1); > > do0(&f0); // ok > do1(&f1); // ok > } > > Error messages are difficult to interpret for a diagnosis, I guess. Note that the first one concerns the caller, while the second one concerns the callee... > Implicite referencing would solve that issue /and/ match semantics /and/ be more consistent /and/ make code nicer. About consistency, I mean that functions are already implicitely dereferenced: do1 does not need to call its arg f using > (*f)(3); > (this version works as well, indeed) When properties are properly implemented, I expect this error message to be different. Currently, it thinks you are trying to call the function f0 and pass its result to do0. -Steve |
Copyright © 1999-2021 by the D Language Foundation