Template for function or delegate (nothing else)

spir denis.spir at gmail.com
Thu Feb 10 09:04:28 PST 2011


On 02/10/2011 02:51 PM, Steven Schveighoffer wrote:
> On Thu, 10 Feb 2011 08:39:13 -0500, spir <denis.spir at 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



More information about the Digitalmars-d-learn mailing list