www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template limits in D2

reply bearophile <bearophileHUGS lycos.com> writes:
I am trying to create a non-dynamic array at compile time, so I have written
this test code:

int sumSqrt(int n) {
    int result = 0;
    while (n) {
        int digit = n % 10;
        n /= 10;
        result += digit * digit;
    }
    return result;
}
template GenSquares(int n) {
    static if (n < 0)
        const int[] GenSquares = [];
    else
        const int[] GenSquares = GenSquares!(n-1) ~ [sumSqrt(n)];
}
void main() {
    const int CHUNK = 1000;
    static const auto squares = cast(int[CHUNK])GenSquares!(CHUNK-1);
}

That code works with D1. But with D2 it gives:
templates_test.d(15): Error: template instance templates_test.GenSquares!(499)
recursive expansion
Do you know why D2 allows less templates?


The second problem is that compile-time functions are nicer, so I'd like to not
use templates when possible. But the following code doesn't work at compile
time, can you tell me why? (I have had to use a not nice temporary struct to
return the static array)

struct S(int N) { int[N] a; }

S!(N) genSquares(int N)() {
    S!(N) s;
    for (int i = 0; i < N; i++) {
        int n = i;
        int m = 0;
        while (n) {
            int digit = n % 10;
            n /= 10;
            m += digit * digit;
        }
        s.a[i] = m;
    }

    return s;
}
void main() {
    const int CHUNK = 1000;
    static const auto squares = genSquares!(CHUNK)().a;
}

Bye and thank you,
bearophile
May 24 2009
parent reply Lutger <lutger.blijdestijn gmail.com> writes:
bearophile wrote:

... 
 
 The second problem is that compile-time functions are nicer, so I'd like to
not use templates when possible. But the following code doesn't work at compile
time, can you tell me why? (I have had to use a 
not nice temporary struct to return the static array)
 
 struct S(int N) { int[N] a; }
 
 S!(N) genSquares(int N)() {
     S!(N) s;
     for (int i = 0; i < N; i++) {
         int n = i;
         int m = 0;
         while (n) {
             int digit = n % 10;
             n /= 10;
             m += digit * digit;
         }
         s.a[i] = m;
     }
 
     return s;
 }
 void main() {
     const int CHUNK = 1000;
     static const auto squares = genSquares!(CHUNK)().a;
 }
 
 Bye and thank you,
 bearophile
I'm not sure why, this code does work: int[] genSquares(int N)() { int[] a; for (int i = 0; i < N; i++) { int n = i; int m = 0; while (n) { int digit = n % 10; n /= 10; m += digit * digit; } a~=m; } return a; } void main() { enum int CHUNK = 1000; enum int[CHUNK] squares = genSquares!(CHUNK)(); } However, it fails as soon as I try do use indexing or set the length of an array. I thought these operations were supposed to be legal, perhaps it is a bug.
May 24 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Lutger escribió:
 bearophile wrote:
 
 ... 
 The second problem is that compile-time functions are nicer, so I'd like to
not use templates when possible. But the following code doesn't work at compile
time, can you tell me why? (I have had to use a 
not nice temporary struct to return the static array)
 struct S(int N) { int[N] a; }

 S!(N) genSquares(int N)() {
     S!(N) s;
     for (int i = 0; i < N; i++) {
         int n = i;
         int m = 0;
         while (n) {
             int digit = n % 10;
             n /= 10;
             m += digit * digit;
         }
         s.a[i] = m;
     }

     return s;
 }
 void main() {
     const int CHUNK = 1000;
     static const auto squares = genSquares!(CHUNK)().a;
 }

 Bye and thank you,
 bearophile
I'm not sure why, this code does work: int[] genSquares(int N)() { int[] a; for (int i = 0; i < N; i++) { int n = i; int m = 0; while (n) { int digit = n % 10; n /= 10; m += digit * digit; } a~=m; } return a; } void main() { enum int CHUNK = 1000; enum int[CHUNK] squares = genSquares!(CHUNK)(); } However, it fails as soon as I try do use indexing or set the length of an array. I thought these operations were supposed to be legal, perhaps it is a bug.
I just debugged it with Descent, and it seems the static array is the problem. It can't be interpreted. But doing this works: --- struct S(int N) { int[] a; } ... s.a ~= m; --- I think static arrays don't work in compile-time functions. Like, you can't return one from a function, so that might be the problem, I don't know.
May 24 2009
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Ary Borenszweig escribió:
 Lutger escribió:
 bearophile wrote:

 ...
 The second problem is that compile-time functions are nicer, so I'd 
 like to not use templates when possible. But the following code 
 doesn't work at compile time, can you tell me why? (I have had to use a 
not nice temporary struct to return the static array)
 struct S(int N) { int[N] a; }

 S!(N) genSquares(int N)() {
     S!(N) s;
     for (int i = 0; i < N; i++) {
         int n = i;
         int m = 0;
         while (n) {
             int digit = n % 10;
             n /= 10;
             m += digit * digit;
         }
         s.a[i] = m;
     }

     return s;
 }
 void main() {
     const int CHUNK = 1000;
     static const auto squares = genSquares!(CHUNK)().a;
 }

 Bye and thank you,
 bearophile
I'm not sure why, this code does work: int[] genSquares(int N)() { int[] a; for (int i = 0; i < N; i++) { int n = i; int m = 0; while (n) { int digit = n % 10; n /= 10; m += digit * digit; } a~=m; } return a; } void main() { enum int CHUNK = 1000; enum int[CHUNK] squares = genSquares!(CHUNK)(); } However, it fails as soon as I try do use indexing or set the length of an array. I thought these operations were supposed to be legal, perhaps it is a bug.
I just debugged it with Descent, and it seems the static array is the problem. It can't be interpreted. But doing this works: --- struct S(int N) { int[] a; } ... s.a ~= m; --- I think static arrays don't work in compile-time functions. Like, you can't return one from a function, so that might be the problem, I don't know.
BTW, I had to debug inside Descent's code to find this. If I debug it using the debugger I'm programming, I can see it stops the execution right at the "s.a[i] = m;" line, without saying why (DMD doesn't say why). It's not much, but I think it's better than "Can't evaluate at compile-time", and might give you more clues about it. :-)
May 24 2009
next sibling parent BCS <none anon.com> writes:
Hello Ary,

 BTW, I had to debug inside Descent's code to find this. If I debug it
 using the debugger I'm programming, I can see it stops the execution
 right at the "s.a[i] = m;" line, without saying why (DMD doesn't say
 why). It's not much, but I think it's better than "Can't evaluate at
 compile-time", and might give you more clues about it. :-)
DMD feature request?
May 24 2009
prev sibling parent Lutger <lutger.blijdestijn gmail.com> writes:
Ary Borenszweig wrote:
...
 
 BTW, I had to debug inside Descent's code to find this. If I debug it 
 using the debugger I'm programming, I can see it stops the execution 
 right at the "s.a[i] = m;" line, without saying why (DMD doesn't say 
 why). It's not much, but I think it's better than "Can't evaluate at 
 compile-time", and might give you more clues about it. :-)
yes it's this: "s.a[i] = m", it doesn't work with dynamic arrays either.
May 24 2009