Thread overview
recursive function call at compile time
Dec 16, 2012
Oleg
Dec 16, 2012
bearophile
Dec 16, 2012
Philippe Sigaud
December 16, 2012
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?
December 16, 2012
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
December 16, 2012
>
>
> 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
}