www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Delegate returning itself

reply "Jonathan Marler" <johnnymarler gmail.com> writes:
Is there a way to create a delegate that returns itself?

alias MyDelegate delegate() MyDelegate;
// OR
alias MyDelegate = MyDelegate delegate();

When I compile this I get:

Error: alias MyDelegate recursive alias declaration

The error makes sense but I still feel like there should be a way 
to create a delegate that returns itself.  Maybe there's 
something I haven't thought of.  Does anyone have an idea on how 
to do this?
Dec 06 2014
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
The problem is the recursive *alias* rather than the delegate. 
Just don't use the alias name inside itself so like

alias MyDelegate = void delegate() delegate();

will work. The first void delegate() is the return value of the 
MyDelegate type.
Dec 06 2014
parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe wrote:
 The problem is the recursive *alias* rather than the delegate. 
 Just don't use the alias name inside itself so like

 alias MyDelegate = void delegate() delegate();

 will work. The first void delegate() is the return value of the 
 MyDelegate type.
Yes I tried that as well. It still doesn't solve the issue. The delegate being returned doesn't return a delegate, it returns the "void" type. You would need to write delegate() delegate() delegate() delegate() ...FOREVER. I can't figure out a way to write this in the language even though the machine code it generates should be quite trivial.
Dec 08 2014
parent reply "Jonathan Marler" <johnnymarler gmail.com> writes:
On Monday, 8 December 2014 at 14:08:33 UTC, Jonathan Marler wrote:
 On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe 
 wrote:
 The problem is the recursive *alias* rather than the delegate. 
 Just don't use the alias name inside itself so like

 alias MyDelegate = void delegate() delegate();

 will work. The first void delegate() is the return value of 
 the MyDelegate type.
Yes I tried that as well. It still doesn't solve the issue. The delegate being returned doesn't return a delegate, it returns the "void" type. You would need to write delegate() delegate() delegate() delegate() ...FOREVER. I can't figure out a way to write this in the language even though the machine code it generates should be quite trivial.
I did some digging and realized that C/C++ have the same problem. I found a nice post on it with 2 potential solutions (http://c-faq.com/decl/recurfuncp.html). I liked the second solution so I wrote up an example in D. If anyone has any other ideas or can think of a way to improve my example feel free to post and let me know, thanks.import std.stdio; struct StateFunc { StateFunc function() func; } StateFunc state1() { writeln("state1"); return StateFunc(&state2); } StateFunc state2() { writeln("state2"); return StateFunc(&state3); } StateFunc state3() { writeln("state3"); return StateFunc(null); } void main(string[] args) { StateFunc state = StateFunc(&state1); while(state.func != null) { state = state.func(); } }
Dec 08 2014
parent reply "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> writes:
On Monday, 8 December 2014 at 14:31:53 UTC, Jonathan Marler wrote:
 On Monday, 8 December 2014 at 14:08:33 UTC, Jonathan Marler 
 wrote:
 On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe 
 wrote:
 The problem is the recursive *alias* rather than the 
 delegate. Just don't use the alias name inside itself so like

 alias MyDelegate = void delegate() delegate();

 will work. The first void delegate() is the return value of 
 the MyDelegate type.
Yes I tried that as well. It still doesn't solve the issue. The delegate being returned doesn't return a delegate, it returns the "void" type. You would need to write delegate() delegate() delegate() delegate() ...FOREVER. I can't figure out a way to write this in the language even though the machine code it generates should be quite trivial.
I did some digging and realized that C/C++ have the same problem. I found a nice post on it with 2 potential solutions (http://c-faq.com/decl/recurfuncp.html). I liked the second solution so I wrote up an example in D. If anyone has any other ideas or can think of a way to improve my example feel free to post and let me know, thanks.import std.stdio; struct StateFunc { StateFunc function() func; } StateFunc state1() { writeln("state1"); return StateFunc(&state2); } StateFunc state2() { writeln("state2"); return StateFunc(&state3); } StateFunc state3() { writeln("state3"); return StateFunc(null); } void main(string[] args) { StateFunc state = StateFunc(&state1); while(state.func != null) { state = state.func(); } }
Nice! Using alias this, you can call the struct directly: struct StateFunc { StateFunc function() func; alias func this; } state = state(); Now there still needs to be a way to just `return &state2;` instead of `return StateFunc(&state2);`...
Dec 08 2014
parent "Jonathan Marler" <johnnymarler gmail.com> writes:
On Monday, 8 December 2014 at 14:38:37 UTC, Marc Sch├╝tz wrote:
 On Monday, 8 December 2014 at 14:31:53 UTC, Jonathan Marler 
 wrote:
 On Monday, 8 December 2014 at 14:08:33 UTC, Jonathan Marler 
 wrote:
 On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe 
 wrote:
 The problem is the recursive *alias* rather than the 
 delegate. Just don't use the alias name inside itself so like

 alias MyDelegate = void delegate() delegate();

 will work. The first void delegate() is the return value of 
 the MyDelegate type.
Yes I tried that as well. It still doesn't solve the issue. The delegate being returned doesn't return a delegate, it returns the "void" type. You would need to write delegate() delegate() delegate() delegate() ...FOREVER. I can't figure out a way to write this in the language even though the machine code it generates should be quite trivial.
I did some digging and realized that C/C++ have the same problem. I found a nice post on it with 2 potential solutions (http://c-faq.com/decl/recurfuncp.html). I liked the second solution so I wrote up an example in D. If anyone has any other ideas or can think of a way to improve my example feel free to post and let me know, thanks.import std.stdio; struct StateFunc { StateFunc function() func; } StateFunc state1() { writeln("state1"); return StateFunc(&state2); } StateFunc state2() { writeln("state2"); return StateFunc(&state3); } StateFunc state3() { writeln("state3"); return StateFunc(null); } void main(string[] args) { StateFunc state = StateFunc(&state1); while(state.func != null) { state = state.func(); } }
Nice! Using alias this, you can call the struct directly: struct StateFunc { StateFunc function() func; alias func this; } state = state(); Now there still needs to be a way to just `return &state2;` instead of `return StateFunc(&state2);`...
Nice addition! I can't think of a way to solve the implicit conversion from function pointer to struct, but not a big deal. I'm mostly glad I found a way to do this with no overhead and no awkward casting. Adding the implicit conversion would be icing on the cake.
Dec 08 2014
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/06/2014 07:28 AM, Jonathan Marler wrote:
 Is there a way to create a delegate that returns itself?
Y combinator helps exactly with that: http://rosettacode.org/wiki/Y_combinator#D Copying the code from there: import std.stdio, std.traits, std.algorithm, std.range; auto Y(S, T...)(S delegate(T) delegate(S delegate(T)) f) { static struct F { S delegate(T) delegate(F) f; alias f this; } return (x => x(x))(F(x => f((T v) => x(x)(v)))); } void main() { // Demo code: auto factorial = Y((int delegate(int) self) => (int n) => 0 == n ? 1 : n * self(n - 1) ); auto ackermann = Y((ulong delegate(ulong, ulong) self) => (ulong m, ulong n) { if (m == 0) return n + 1; if (n == 0) return self(m - 1, 1); return self(m - 1, self(m, n - 1)); }); writeln("factorial: ", 10.iota.map!factorial); writeln("ackermann(3, 5): ", ackermann(3, 5)); } Ali
Dec 08 2014