Thread overview
Generic callables
Nov 16, 2004
Daniel Keep
Nov 16, 2004
Russ Lewis
Nov 16, 2004
Daniel Keep
Nov 17, 2004
Charlie
Nov 17, 2004
Stewart Gordon
November 16, 2004
It's me again!  Sorry about the continual posting :P

I've been playing a bit with functional constructs in D, and I've also been looking into making a event framework.

The main drawback of both of these in D is that there is no way to generically express a callable without specializing for both function and delegate.

In some cases, this isn't too big a problem (for example, with my functional templates, the function and delegate code can be derived from the specified types), but it's a killer for events.

The problem is that given, say

# int function(char[], float, SomeFunkyStruct)

There's no way to derive the corresponding delegate.  You would either have to specify all the types manually (and thus force your template to accept a specific number of types), or specify the function and delegate in full to the template.

I was thinking about a possible solution, and I was wondering, is there a chance of getting some kind of generic "callable" type in D?

Essentially, "callable" would work in much the same way as function and template:

# alias int function(char[], float, SomeFunkyStruct) fproto;
# alias int delegate(char[], float, SomeFunkyStruct) dproto;
# alias int callable(char[], float, SomeFunkyStruct) cproto;

Now, you would be able to (implicitly) cast function pointers or delegates to callables...

# fproto foo;
# cproto bar = foo;

...but you would not be allowed to cast callables to either function pointers or delegates.

This is because the "callable" variables would be much like delegates--they would have both a function pointer, and a this pointer.  The trick here is that the this pointer can be null (unlike with delegates).

If the this pointer is not null, then it gets pushed last (as per normal), and the function is called.  If the this pointer IS null, then it simply doesn't get pushed at all.

The advantage of this is that it would allow us to support both delegates and function pointers in code without having to explicitly code for both, but it would also allow us to template generic callable types.

Anyway, just thought I'd share my idea on the off chance Walter likes it :P

	-- Daniel "I wonder..."
November 16, 2004
I'm increasingly coming to the conclusion that we should almost never use function callbacks; we should almost always use delegates.

You can create a wrapper where a delegate calls a function by using a stack delegate.  Technically, you're not supposed to save a stack delegate after the frame goes away, but if you never use any of the stack variables, I think that's ok.  The following program compiled and ran ok:

> import std.string;
> import std.stdio;
>  char[] foo(int i,char c,long l) {
>   return format("%d %s %d", i,c,l);
> }
>  void main() {
>   char[] delegate(int,char,long) bar =
>          delegate char[](int i,char c,long l) { return foo(i,c,l); };
>    writef("%s\n", bar(1,'a',2));
> }

And produced this output:

> 1 a 2

November 16, 2004
I suppose you're right.  It probably helps that you can always wrap a function in a delegate (even if it looks a tad messy).

Thanks for the insight.

Russ Lewis wrote:
> I'm increasingly coming to the conclusion that we should almost never use function callbacks; we should almost always use delegates.
> 
> You can create a wrapper where a delegate calls a function by using a stack delegate.  Technically, you're not supposed to save a stack delegate after the frame goes away, but if you never use any of the stack variables, I think that's ok.  The following program compiled and ran ok:
> 
>> import std.string;
>> import std.stdio;
>>  char[] foo(int i,char c,long l) {
>>   return format("%d %s %d", i,c,l);
>> }
>>  void main() {
>>   char[] delegate(int,char,long) bar =
>>          delegate char[](int i,char c,long l) { return foo(i,c,l); };
>>    writef("%s\n", bar(1,'a',2));
>> }
> 
> 
> And produced this output:
> 
>> 1 a 2
> 
> 
November 17, 2004
Walter has said hes going to unify functions and delegates for 2.0

Charlie

In article <cnddh6$n35$1@digitaldaemon.com>, Daniel Keep says...
>
>I suppose you're right.  It probably helps that you can always wrap a function in a delegate (even if it looks a tad messy).
>
>Thanks for the insight.
>
>Russ Lewis wrote:
>> I'm increasingly coming to the conclusion that we should almost never use function callbacks; we should almost always use delegates.
>> 
>> You can create a wrapper where a delegate calls a function by using a stack delegate.  Technically, you're not supposed to save a stack delegate after the frame goes away, but if you never use any of the stack variables, I think that's ok.  The following program compiled and ran ok:
>> 
>>> import std.string;
>>> import std.stdio;
>>> 
>>> char[] foo(int i,char c,long l) {
>>>   return format("%d %s %d", i,c,l);
>>> }
>>> 
>>> void main() {
>>>   char[] delegate(int,char,long) bar =
>>>          delegate char[](int i,char c,long l) { return foo(i,c,l); };
>>> 
>>>   writef("%s\n", bar(1,'a',2));
>>> }
>> 
>> 
>> And produced this output:
>> 
>>> 1 a 2
>> 
>> 


November 17, 2004
Charlie wrote:
> Walter has said hes going to unify functions and delegates for 2.0
<snip top of upside-down reply>

At the moment, the only problem with delegates is that the this pointer can't be null.  Presumably, the plan is to enable this by implicitly converting functions to delegates.

But whatever happens, we will still need plain function pointers for interfacing with foreign APIs.

Stewart.