www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - recursive function call at compile time

reply "Oleg" <code.viator gmail.com> writes:
Hello.
I want use recursion, but in my situation compiler doesn't 
correct work.

import std.stdio;

struct MyStruct(uint K)
{
     real[K] data;

     auto getSmaller()
     {
         MyStruct!(K-1) ret;
         foreach( no, ref d; ret.data )
             d = data[no];
         return ret;
     }

     real recursionAlgo()
     {
         static if( K == 1 ) return data[0];
         else
         {
             real sum = 0;
             foreach( i; 1 .. K )
                 sum += getSmaller().recursionAlgo();
             return sum;
         }
     }
}

void main()
{
     MyStruct!(5) a;
     a.data = [ 1, 2, 3, 4, 5 ];
     writeln( a.recursionAlgo() );
}

at compile time i have errors
./recursion.d(7): Error: index 4294967295 overflow for static 
array
./recursion.d(7): Error: index 4294967294 overflow for static 
array
.... etc

i think it's happens because compiler call 'recursionAlgo()' 
where it should not be ( K == 1 )

how to turn off compile time calculation in this part of code?
Dec 16 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Oleg:

 at compile time i have errors
 ./recursion.d(7): Error: index 4294967295 overflow for static 
 array
 ./recursion.d(7): Error: index 4294967294 overflow for static 
 array
 .... etc
It prints a little too many of those...
 call 'recursionAlgo()' where it should not be ( K == 1 )
The first problem to fix in your code is visible here, it's not a CTFE problem: struct MyStruct(uint K) { real[K] data; auto getSmaller() { MyStruct!(K - 1) ret; } } void main() { MyStruct!5 a; } When you instantiate MyStruct!5, it tries to define ret, so it instantiates MyStruct!4, MyStruct!3, ... and so on. You have to put a static if or something else to stop that. Bye, bearophile
Dec 16 2012
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
 When you instantiate MyStruct!5, it tries to define ret, so it
 instantiates MyStruct!4, MyStruct!3, ... and so on. You have to put a
 static if or something else to stop that.
Like this: import std.stdio; struct MyStruct(uint K) if (K > 0) // Only to disable direct creation for K==0 { real[K] data; static if (K > 1) // getSmaller only exists for K > 1 MyStruct!(K-1) getSmaller() { MyStruct!(K-1) ret; foreach( no, ref d; ret.data ) d = data[no]; return ret; } real recursionAlgo() { static if( K == 1 ) return data[0]; else { real sum = 0; foreach( i; 1 .. K ) sum += getSmaller().recursionAlgo(); return sum; } } } void main() { MyStruct!(5) a; a.data = [ 1, 2, 3, 4, 5 ]; writeln( a.recursionAlgo() ); // 24 }
Dec 16 2012