www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Generic callables

reply Daniel Keep <daniel.keep dummy.gmail.com> writes:
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..."
Nov 16 2004
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
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

Nov 16 2004
parent reply Daniel Keep <daniel.keep dummy.gmail.com> writes:
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


Nov 16 2004
parent reply Charlie <Charlie_member pathlink.com> writes:
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



Nov 17 2004
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Charlie wrote:
 Walter has said hes going to unify functions and delegates for 2.0

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.
Nov 17 2004