www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Create a delegate function

reply "Prudence" <Pursuit Happyness.All> writes:
I have code setup in such a way that I call a user defined 
function, e.g.,

void myFunc(Data d)
{
....
}

myFunc has to be passed to the main code using something like

void SetFunc(void function(Data) func) { ... func(myData); }

What I would like to do is, instead of having to pass data to 
myFunc(and use the type Data in all the function types), is to 
sort of create a delegate:

what I want to do:

void myFunc()
{
       this.d;  // Ok, because somehow this = Data;
}

then, of course,

void SetFunc(void delegate() func) { func.context = myData; 
func(); }




void delegate() dg =
{
	auto t = this;
	return;
};

doesn't even work because this is not defined.


My guess this is impossible without compiler support.

effectively though, I don't see why we can't use this(because 
myFunc is being executed in a context, I simply want to set it to 
the right one so that the user can take advantage of it... 
instead of having to pass an argument instead.


Any ideas how to do this? It seems we can't actually create 
"delegate objects" but only delegate pointers? (simply because of 
the restrictions the compiler places on *this*. (can't be used 
outside of a context, even though we can always guarantee it is 
in a context)

How bout a new syntax for such concepts?

void delegate!T(...) dg
{

}

// identical to

void dg(T this, ...)
{

}


Hence, to call dg, we have to pass it a "this" object... hence it 
has a context. They can be called just like functions. dg(myData, 
...);
Sep 05 2015
next sibling parent "BBasile" <bb.temp gmx.com> writes:
On Saturday, 5 September 2015 at 18:00:53 UTC, Prudence wrote:
 I have code setup in such a way that I call a user defined 
 function, e.g.,

 void myFunc(Data d)
 {
 ....
 }

 myFunc has to be passed to the main code using something like

 void SetFunc(void function(Data) func) { ... func(myData); }

 What I would like to do is, instead of having to pass data to 
 myFunc(and use the type Data in all the function types), is to 
 sort of create a delegate:

 what I want to do:

 void myFunc()
 {
       this.d;  // Ok, because somehow this = Data;
 }

 then, of course,

 void SetFunc(void delegate() func) { func.context = myData; 
 func(); }




 void delegate() dg =
 {
 	auto t = this;
 	return;
 };

 doesn't even work because this is not defined.


 My guess this is impossible without compiler support.

 effectively though, I don't see why we can't use this(because 
 myFunc is being executed in a context, I simply want to set it 
 to the right one so that the user can take advantage of it... 
 instead of having to pass an argument instead.


 Any ideas how to do this? It seems we can't actually create 
 "delegate objects" but only delegate pointers? (simply because 
 of the restrictions the compiler places on *this*. (can't be 
 used outside of a context, even though we can always guarantee 
 it is in a context)

 How bout a new syntax for such concepts?

 void delegate!T(...) dg
 {

 }

 // identical to

 void dg(T this, ...)
 {

 }


 Hence, to call dg, we have to pass it a "this" object... hence 
 it has a context. They can be called just like functions. 
 dg(myData, ...);
Wow, it's hard to get what you mean. It's a bit confuse. But, IIUC you want to link the parameter value to the delegate type ? If so then it's time for you to lean 'std.typecons.Tuple' and 'std.typecons.tuple'. For example, is this what you meant ? --- module runnable; import std.stdio; import std.typecons; import std.traits; alias Fun = void function(int); alias FunAndData = Tuple!(Fun, ParameterTypeTuple!Fun); struct MainCode { int myData; void setFunc(FunAndData funAndData) { funAndData[0](funAndData[1..$]); } } void test(int param) { writeln(param); } void main(string[] args) { MainCode mainCode; mainCode.setFunc(tuple(&test,46)); } ---
Sep 05 2015
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 5 September 2015 at 18:00:53 UTC, Prudence wrote:
 I have code setup in such a way that I call a user defined 
 function, e.g.,

 void myFunc(Data d)
 {
 ....
 }

 myFunc has to be passed to the main code using something like
You can do that if and only if the this is the last argument to the function and is a pointer. Even then, you're kinda hacking it, but with casts you can make it work: struct Test { int a; } void foo(Test* _this) { _this.a = 10; } void main() { auto _this = new Test(); void delegate() dg; dg.funcptr = cast(typeof(dg.funcptr)) &foo; dg.ptr = _this; dg(); import std.stdio; writeln(_this.a); } You could probably put that in a template that does better type checking. But the idea is that a delegate is simply a pair of function pointer and context pointer. When you call it, it automatically adds the context pointer as the last hidden argument to the function. Knowing how it works at the low level, we can use some casts to get the compiler to trust us and make it work. Similarly with arguments: struct Test { int a; } void foo(int a, Test* _this) { _this.a = 10 + a; } void main() { auto _this = new Test(); void delegate(int) dg; dg.funcptr = cast(typeof(dg.funcptr)) &foo; dg.ptr = _this; dg(10); import std.stdio; writeln(_this.a); } To type check this, you could probably use ParameterTypeTuple!foo[0 .. $-1] and check for match there on the typeof(dg.funcptr). And check return value and that the last argument is indeed a pointer of the type you are giving.
Sep 05 2015