inner functions calling each other - how to do this with inner struct?

Ivan Kazmenko via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Feb 3 06:01:24 PST 2016


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.



More information about the Digitalmars-d-learn mailing list