digitalmars.D.learn - inner functions calling each other - how to do this with inner struct?
- Ivan Kazmenko (109/109) Feb 03 2016 Hi,
- Adam D. Ruppe (5/6) Feb 03 2016 Read my post here:
- Ivan Kazmenko (26/29) Feb 03 2016 This indeed works without any other tricks such as compile-time
Hi, 1. What works. Inside a function (outerFun), I've got inner functions fun1 and fun2 which have to recursively call each other. Just writing them one after the other does not work. I've managed to find a trick to make it work though, which is to add empty compile-time parameters to fun1 and fun2: ----- import std.stdio; void outerFun () { void fun1 () (int x) { writeln (x); if (x > 0) fun2 (x - 1); } void fun2 () (int y) { writeln (y); if (y > 1) fun1 (y - 2); } fun2 (10); } void main () {outerFun ();} ----- 2. What doesn't work. Next, I'd like to have an inner function fun1 and an inner struct S with a method fun2, and an instance s of struct S. I want to be able to call s.fun2 from fun1 and fun1 back from s.fun2. Now, I can't figure out how to do that. The same trick does not seem to work: ----- import std.stdio; void outerFun () { struct S () { void fun2 (int x) { writeln (x); if (x > 0) fun1 !() (x - 1); } } S !() s; void fun1 () (int y) { writeln (y); if (y > 1) s.fun2 (y - 2); } fun1 (10); } void main () {outerFun ();} ----- Here are the errors I get: ----- test2.d(7): Error: template instance fun1!() template 'fun1' is not defined, did you mean fun2? test2.d(11): Error: template instance test2.outerFun.S!() error instantiating ----- So, is this mutual recursion (inner function and method of a fixed instance of an inner struct) possible? This does not seem theoretically wrong: we have to maintain exactly one outer context pointer (to outerFun's current stack frame) for each recursive call. 3. What also doesn't work. Here is another attempt, where the outer scope is a struct, not a function. Again, I want to be able to call fun1 from s.fun2 and s.fun2 from fun1. ----- import std.stdio; struct outerStruct { struct S { void fun2 (int x) { writeln (x); if (x > 0) fun1 (x - 1); } } S s; void fun1 (int y) { writeln (y); if (y > 1) s.fun2 (y - 2); } } void main () {outerStruct os; os.fun1 (10);} ----- With no compile-time parameters, this just says: ----- test3.d(7): Error: this for fun1 needs to be type outerStruct not type S ----- Apparently, the call to fun1 is not able to get the context pointer to outerStruct os and use it to call fun1. Again, I don't see a theoretical limitation here. Did I fail to express my intent to the compiler, or is what I want impossible with the current implementation? 4. Module scope. At module scope (no outer context pointer needed), everything works fine without the need for tricks: ----- import std.stdio; struct S { void fun2 (int x) { writeln (x); if (x > 0) fun1 (x - 1); } } S s; void fun1 (int y) { writeln (y); if (y > 1) s.fun2 (y - 2); } void main () {fun1 (10);} ----- Ivan Kazmenko.
Feb 03 2016
On Wednesday, 3 February 2016 at 14:01:24 UTC, Ivan Kazmenko wrote:1. What works.Read my post here: then see if you can use the same reasoning on your problem.
Feb 03 2016
On Wednesday, 3 February 2016 at 15:09:35 UTC, Adam D. Ruppe wrote:Read my post here: then see if you can use the same reasoning on your problem.This indeed works without any other tricks such as compile-time parameters: ----- import std.stdio; void outerFun () { struct Holder { static struct S { void fun2 (int x) { writeln (x); if (x > 0) fun1 (x - 1); } } static S s; static void fun1 (int y) { writeln (y); if (y > 1) s.fun2 (y - 2); } } Holder.fun1 (10); } void main () {outerFun ();} ----- Thank you! Ivan Kazmenko.
Feb 03 2016