Struct array assign?

bearophile bearophileHUGS at lycos.com
Sat Jan 7 16:19:04 PST 2012


Currently D allows code like this (I think you are supposed to use opAssign here...):


struct MyTypedefInt {
    int x;
    this(int xx) { this.x = xx; }
    // void opAssign(int xx) { this.x = xx; }
}
void main() {
    MyTypedefInt x = 1; // OK
}



But if you put the elements into an array they are refused (the same problem happens with BigInts, etc):


struct MyTypedefInt {
    int x;
    this(int xx) { this.x = xx; }
    // void opAssign(int xx) { this.x = xx; }
}
void main() {
    MyTypedefInt[2] a3 = [1, 2]; // Error: cannot implicitly convert expression
}



This too is not accepted:

struct MyTypedefInt {
    int x;
    this(int xx) { this.x = xx; }
    // void opAssign(int xx) { this.x = xx; }
}
void main() {
    MyTypedefInt[2] a3 = [{ 1 }, { 2 }];
}


test.d(7): Error: struct MyTypedefInt has constructors, cannot use { initializers }, use MyTypedefInt( initializers ) instead
test.d(7): Error: struct MyTypedefInt has constructors, cannot use { initializers }, use MyTypedefInt( initializers ) instead


This is accepted:

struct MyTypedefInt {
    int x;
    this(int xx) { this.x = xx; }
}
void main() {
    MyTypedefInt[2] a3 = [MyTypedefInt(1), MyTypedefInt(2)];
}


but it's not so nice to write, even if you shorten the name of MyTypedefInt to a single char:

struct MyTypedefInt {
    int x;
    this(int xx) { this.x = xx; }
}
void main() {
    alias MyTypedefInt M;
    MyTypedefInt[2] a3 = [M(1), M(2)];
}



So is it possible and wise to support code like:
MyTypedefInt[2] a3 = [1, 2];
MyTypedefInt[] a4 = [1, 2];
MyTypedefInt[][] a5 = [[1, 2], [3, 4]];


Here is an usage example of code like that, this is Ada code:


subtype Number is Natural range 0 .. 9;
subtype Valid_Number is Number range 1 .. 9;
type Board is array (Valid_Number, Valid_Number) of Number;
Sample_Board : Board := (1 => (3, 9, 4, 0, 0, 2, 6, 7, 0),
                         2 => (0, 0, 0, 3, 0, 0, 4, 0, 0),
                         3 => (5, 0, 0, 6, 9, 0, 0, 2, 0),
                         4 => (0, 4, 5, 0, 0, 0, 9, 0, 0),
                         5 => (6, 0, 0, 0, 0, 0, 0, 0, 7),
                         6 => (0, 0, 7, 0, 0, 0, 5, 8, 0),
                         7 => (0, 1, 0, 0, 6, 7, 0, 0, 8),
                         8 => (0, 0, 9, 0, 0, 8, 0, 0, 0),
                         9 => (0, 2, 6, 4, 0, 0, 7, 3, 5));



With the change I have suggested (plus library-defined TypeDef and SubRange) you are able to write something similar in D2 too (here I have ignored Valid_Number, the type of the array index), despite it looks a bit worse:


alias TypeDef!(SubRange!(size_t, 0, 10)) Number;
alias TypeDef!(Number[9][9]) Board;
Board sampleBoard = [[3, 9, 4, 0, 0, 2, 6, 7, 0],
                     [0, 0, 0, 3, 0, 0, 4, 0, 0],
                     [5, 0, 0, 6, 9, 0, 0, 2, 0],
                     [0, 4, 5, 0, 0, 0, 9, 0, 0],
                     [6, 0, 0, 0, 0, 0, 0, 0, 7],
                     [0, 0, 7, 0, 0, 0, 5, 8, 0],
                     [0, 1, 0, 0, 6, 7, 0, 0, 8],
                     [0, 0, 9, 0, 0, 8, 0, 0, 0],
                     [0, 2, 6, 4, 0, 0, 7, 3, 5]];


This *encourages* to write D code with more static safety, that for me is one of the main purposes of using static typing in the first place. D is designed to write more than just game engines :-)

Bye,
bearophile


More information about the Digitalmars-d mailing list