Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
December 06, 2014 Delegate returning itself | ||||
---|---|---|---|---|
| ||||
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? |
December 06, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | 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. |
December 08, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | 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.
|
December 08, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | 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(); } } |
December 08, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | 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);`...
|
December 08, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | 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.
|
December 08, 2014 Re: Delegate returning itself | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | 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 |
Copyright © 1999-2021 by the D Language Foundation