www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Fixed size array initialization

reply rumbu <rumbu rumbu.ro> writes:
I know that according to language spec 
(https://dlang.org/spec/arrays.html#static-init-static) you can 
skip declaring all your elements in a fixed size array.

I'm just recovering from a bug which took me one day to discover 
because of this.

I have a large static initialized array, let's say int[155], and 
I forgot to declare the last element:

int[155] myarray = [
   a,
   b,
   c,
   ...
   //forgot to declare the 155th element
];

I took for granted that the compiler will warn me about the fact 
that my number of elements doesn't match the array declaration 
but I was wrong.

Does it worth to fill an enhancement on this, or this is intended 
behavior?
Feb 10 2018
next sibling parent reply b2.temp gmx.com <b2.temp gmx.com> writes:
On Saturday, 10 February 2018 at 10:55:30 UTC, rumbu wrote:
 I know that according to language spec 
 (https://dlang.org/spec/arrays.html#static-init-static) you can 
 skip declaring all your elements in a fixed size array.

 I'm just recovering from a bug which took me one day to 
 discover because of this.

 I have a large static initialized array, let's say int[155], 
 and I forgot to declare the last element:

 int[155] myarray = [
   a,
   b,
   c,
   ...
   //forgot to declare the 155th element
 ];

 I took for granted that the compiler will warn me about the 
 fact that my number of elements doesn't match the array 
 declaration but I was wrong.

 Does it worth to fill an enhancement on this, or this is 
 intended behavior?
I used to agree (https://issues.dlang.org/show_bug.cgi?id=17341) and even patched the compiler to emit a deprecation in this case. Then i discovered that druntime for example relies on this. The classic use case is to init a LUT where only a few elements need a non-default value, for example: ``` bool[char.max] lut = [10:true, 13:true, 9: true]; assert(!lut[46]); assert(lut[9]); ``` which can be useful.
Feb 10 2018
parent reply rumbu <rumbu rumbu.ro> writes:
On Saturday, 10 February 2018 at 12:28:16 UTC, b2.temp wrote:
 On Saturday, 10 February 2018 at 10:55:30 UTC, rumbu wrote:
 I know that according to language spec 
 (https://dlang.org/spec/arrays.html#static-init-static) you 
 can skip declaring all your elements in a fixed size array.

 I'm just recovering from a bug which took me one day to 
 discover because of this.

 I have a large static initialized array, let's say int[155], 
 and I forgot to declare the last element:

 int[155] myarray = [
   a,
   b,
   c,
   ...
   //forgot to declare the 155th element
 ];

 I took for granted that the compiler will warn me about the 
 fact that my number of elements doesn't match the array 
 declaration but I was wrong.

 Does it worth to fill an enhancement on this, or this is 
 intended behavior?
I used to agree (https://issues.dlang.org/show_bug.cgi?id=17341) and even patched the compiler to emit a deprecation in this case. Then i discovered that druntime for example relies on this. The classic use case is to init a LUT where only a few elements need a non-default value, for example: ``` bool[char.max] lut = [10:true, 13:true, 9: true]; assert(!lut[46]); assert(lut[9]); ``` which can be useful.
In this case, it there any way to be sure that I declared all the elements I intended? Obviously, without counting them by hand.
Feb 10 2018
parent reply b2.temp gmx.com <b2.temp gmx.com> writes:
On Saturday, 10 February 2018 at 14:35:52 UTC, rumbu wrote:
 On Saturday, 10 February 2018 at 12:28:16 UTC, b2.temp wrote:
 On Saturday, 10 February 2018 at 10:55:30 UTC, rumbu wrote:
 I know that according to language spec 
 (https://dlang.org/spec/arrays.html#static-init-static) you 
 can skip declaring all your elements in a fixed size array.

 I'm just recovering from a bug which took me one day to 
 discover because of this.

 I have a large static initialized array, let's say int[155], 
 and I forgot to declare the last element:

 int[155] myarray = [
   a,
   b,
   c,
   ...
   //forgot to declare the 155th element
 ];

 I took for granted that the compiler will warn me about the 
 fact that my number of elements doesn't match the array 
 declaration but I was wrong.

 Does it worth to fill an enhancement on this, or this is 
 intended behavior?
I used to agree (https://issues.dlang.org/show_bug.cgi?id=17341) and even patched the compiler to emit a deprecation in this case. Then i discovered that druntime for example relies on this. The classic use case is to init a LUT where only a few elements need a non-default value, for example: ``` bool[char.max] lut = [10:true, 13:true, 9: true]; assert(!lut[46]); assert(lut[9]); ``` which can be useful.
In this case, it there any way to be sure that I declared all the elements I intended? Obviously, without counting them by hand.
At the level of the library use a template. At the level of the compiler: no. Not only not all elements are required but they also don't need to be declared in order (static array initialization, like in the example beyond). It would be possible to put a compiler warning but warnings are not in the D philosophy (one consequence is that many people, like me use -de all the time, making a possible warning not compatible with the legit uses of the "partial array initialization"). By the way i said i did change the compiler. Actually i even captured the session to promote my IDE: http://sendvid.com/c00x7nps.
Feb 10 2018
parent reply rumbu <rumbu rumbu.ro> writes:
On Saturday, 10 February 2018 at 14:55:49 UTC, b2.temp wrote:
 On Saturday, 10 February 2018 at 14:35:52 UTC, rumbu wrote:
 In this case, it there any way to be sure that I declared all 
 the elements I intended? Obviously, without counting them by 
 hand.
At the level of the library use a template.
Sorry, but I don't get it. Can you elaborate, please? This is the array in question: https://github.com/rumbu13/decimal/blob/master/src/decimal/integrals.d#L2072 First time, I tried to use mixins to generate the array, in order to avoid writing the same thing again and again. The mixin solution was nice until the compiler served me a nice Out of Memory error, that's why I finally used a hand-written array.
 At the level of the compiler: no. Not only not all elements are 
 required but they also don't need to be declared in order 
 (static array initialization, like in the example beyond).

 It would be possible to put a compiler warning but warnings are 
 not in the D philosophy (one consequence is that many people, 
 like me use -de all the time, making a possible warning not 
 compatible with the legit uses of the "partial array 
 initialization").

 By the way i said i did change the compiler. Actually i even 
 captured the session to promote my IDE: 
 http://sendvid.com/c00x7nps.
Feb 10 2018
parent Seb <seb wilzba.ch> writes:
On Saturday, 10 February 2018 at 15:54:03 UTC, rumbu wrote:
 On Saturday, 10 February 2018 at 14:55:49 UTC, b2.temp wrote:
 On Saturday, 10 February 2018 at 14:35:52 UTC, rumbu wrote:
 In this case, it there any way to be sure that I declared all 
 the elements I intended? Obviously, without counting them by 
 hand.
At the level of the library use a template.
Sorry, but I don't get it. Can you elaborate, please?
https://github.com/dlang/phobos/pull/4936
Feb 10 2018
prev sibling next sibling parent Kagamin <spam here.lot> writes:
https://issues.dlang.org/show_bug.cgi?id=481#c40
Feb 10 2018
prev sibling next sibling parent reply psychoticRabbit <meagain meagain.com> writes:
On Saturday, 10 February 2018 at 10:55:30 UTC, rumbu wrote:
 I have a large static initialized array, let's say int[155], 
 and I forgot to declare the last element:

 int[155] myarray = [
   a,
   b,
   c,
   ...
   //forgot to declare the 155th element
 ];
Well, in C.. I can do: int arr[2] = { [0]=10, [1]=20 }; I cannot work out how to do that in D yet (anyone know??) In the meantime, I'd suggest doing it this way, as you're more likely to see that whether you forgot an element: int[2] arr; { arr[0] = 10; arr[1] = 20; }
Feb 10 2018
parent reply psychoticRabbit <meagain meagain.com> writes:
On Sunday, 11 February 2018 at 01:13:00 UTC, psychoticRabbit 
wrote:
 Well, in C.. I can do:

 int arr[2] = { [0]=10, [1]=20 };

 I cannot work out how to do that in D yet (anyone know??)
Oh. just worked it out after reading this thread ;-) int[2] arr = [ 0:10, 1:20 ];
Feb 10 2018
parent rumbu <rumbu rumbu.ro> writes:
On Sunday, 11 February 2018 at 01:26:59 UTC, psychoticRabbit 
wrote:
 On Sunday, 11 February 2018 at 01:13:00 UTC, psychoticRabbit 
 wrote:
 Well, in C.. I can do:

 int arr[2] = { [0]=10, [1]=20 };

 I cannot work out how to do that in D yet (anyone know??)
Oh. just worked it out after reading this thread ;-) int[2] arr = [ 0:10, 1:20 ];
This is indeed the most simple and elegant solution. Thanks.
Feb 10 2018
prev sibling parent reply rjframe <dlang ryanjframe.com> writes:
On Sat, 10 Feb 2018 10:55:30 +0000, rumbu wrote:

 I know that according to language spec
 (https://dlang.org/spec/arrays.html#static-init-static) you can skip
 declaring all your elements in a fixed size array.
 
 I'm just recovering from a bug which took me one day to discover because
 of this.
 
 I have a large static initialized array, let's say int[155], and I
 forgot to declare the last element:
 
 int[155] myarray = [
    a,
    b,
    c,
    ...
    //forgot to declare the 155th element
 ];
 
 I took for granted that the compiler will warn me about the fact that my
 number of elements doesn't match the array declaration but I was wrong.
 
 Does it worth to fill an enhancement on this, or this is intended
 behavior?
If you separate initialization to a static this, you'll get a compile error: ``` immutable uint256[78] pow10_256; static this() { // Error: mismatched array lengths, 78 and 2 pow10_256 = [ uint256(1UL), uint256(10UL) ]; } ``` Or if you know that no element should be the object's init value, you could do a static foreach to validate that at compile-time. You could also generate the elements at compile-time (this could use some improvement, and should be generalized so a single function can generate fillers for your other arrays as well): ``` immutable uint256[78] pow10_256; static this() { // Uncomment this to view the generated code. Helpful for debugging. //pragma(msg, GenPow10_256Initializer); mixin(GenPow10_256Initializer); } static string GenPow10_256Initializer() { import std.range : repeat; import std.conv : text; string code = "pow10_256 = [\n"; foreach(i; 0..78) { code ~= ` uint256("1` ~ '0'.repeat(i).text ~ `")` ~ ",\n"; } code = code[0..$-2]; // Remove trailing comma. code ~= "\n];"; return code; } ```
Feb 11 2018
parent rumbu <rumbu rumbu.ro> writes:
On Sunday, 11 February 2018 at 14:06:32 UTC, rjframe wrote:
 On Sat, 10 Feb 2018 10:55:30 +0000, rumbu wrote:

 If you separate initialization to a static this, you'll get a 
 compile error:

 ```
 immutable uint256[78] pow10_256;

 static this() {
     // Error: mismatched array lengths, 78 and 2
     pow10_256 = [
         uint256(1UL),
         uint256(10UL)
     ];
 }
 ```
Yes, this was in fact the idea of https://github.com/dlang/phobos/pull/4936 Didn't like it, sorry.
 Or if you know that no element should be the object's init 
 value, you could do a static foreach to validate that at 
 compile-time.
Nice idea too, but this will significantly increase compilation time.
 You could also generate the elements at compile-time (this 
 could use some improvement, and should be generalized so a 
 single function can generate fillers for your other arrays as 
 well):

 ```
 immutable uint256[78] pow10_256;

 static this() {
     // Uncomment this to view the generated code. Helpful for 
 debugging.
     //pragma(msg, GenPow10_256Initializer);
     mixin(GenPow10_256Initializer);
 }

 static string GenPow10_256Initializer() {
     import std.range : repeat;
     import std.conv : text;

     string code = "pow10_256 = [\n";
     foreach(i; 0..78) {
         code ~= `    uint256("1` ~ '0'.repeat(i).text ~ `")` ~ 
 ",\n";
     }
     code = code[0..$-2]; // Remove trailing comma.
     code ~= "\n];";
     return code;
 }
 ```
As I said in my previous comments, this was the initial approach for all the arrays there (I'm a very lazy person, believe me) but the compiler complained with a nice "Out of memory" error, that's why I ended writing the array elements by hand.
Feb 11 2018