digitalmars.D.learn - Delegate returning itself
- Jonathan Marler (10/10) Dec 06 2014 Is there a way to create a delegate that returns itself?
- Adam D. Ruppe (5/5) Dec 06 2014 The problem is the recursive *alias* rather than the delegate.
- Jonathan Marler (7/12) Dec 08 2014 Yes I tried that as well. It still doesn't solve the issue. The
- Jonathan Marler (33/48) Dec 08 2014 I did some digging and realized that C/C++ have the same problem.
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (10/61) Dec 08 2014 Nice! Using alias this, you can call the struct directly:
- Jonathan Marler (6/71) Dec 08 2014 Nice addition! I can't think of a way to solve the implicit
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (26/27) Dec 08 2014 Y combinator helps exactly with that:
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
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
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
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: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(); } }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
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: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);`...On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe wrote: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(); } }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
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: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.On Monday, 8 December 2014 at 14:08:33 UTC, Jonathan Marler wrote: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);`...On Saturday, 6 December 2014 at 15:46:16 UTC, Adam D. Ruppe wrote: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(); } }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
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