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

Reply via email to