Array slice assign syntax

bearophile bearophileHUGS at lycos.com
Tue Nov 15 19:24:25 PST 2011


The Bugzilla issues that I really care about is a not an useless long list, it's about fifteen items long, and this post is about one of them.

I think current array slice assign syntax is a bit messy, and I think this should be addressed.

Kenji Hara has recently written a very nice program (that here I have modified a bit for clarity) that shows the current array assign situation:


import std.stdio, std.typetuple;

void main() {
    writeln("Rhs is an array, is it compilable?");
    writeln("a\t/ b\t\ta=b\ta[]=b\ta=b[]\ta[]=b[]");

    foreach (i, Lhs; TypeTuple!(int[3], int[]))
        foreach (j, Rhs; TypeTuple!(int[3], int[])) {
            writef("%s\t/ %s  ", Lhs.stringof, Rhs.stringof);
            Lhs a = [0,0,0];
            Rhs b = [1,2,3];
            writef("\t%s", __traits(compiles, { a   = b;   }));
            writef("\t%s", __traits(compiles, { a[] = b;   }));
            writef("\t%s", __traits(compiles, { a   = b[]; }));
            writef("\t%s", __traits(compiles, { a[] = b[]; }));
            writeln();
        }


    writeln("\nRhs is a element, is it compilable?");
    writeln("a\t\t\ta=N\ta[]=N\ta[0..2]=N");

    foreach (Lhs; TypeTuple!(int[3], int[])) {
        writef("%s\t\t", Lhs.stringof);
        Lhs a = [0,0,0];
        writef("\t%s", __traits(compiles, { a       = 9; }));
        writef("\t%s", __traits(compiles, { a[]     = 9; }));
        writef("\t%s", __traits(compiles, { a[0..2] = 9; }));
        writeln();
    }
}



Currently (DMD 2.057head, despite I think Walter has not updated DMD version number yet) it prints:


Rhs is an array, is it compilable?
a       / b             a=b     a[]=b   a=b[]   a[]=b[]
int[3u] / int[3u]       true    true    true    true
int[3u] / int[]         true    true    true    true
int[]   / int[3u]       true    true    true    true
int[]   / int[]         true    true    true    true

Rhs is a element, is it compilable?
a                       a=N     a[]=N   a[0..2]=N
int[3u]                 true    true    true
int[]                   false   true    true



This also means this is currently accepted:

void main() {
    int[3] a;
    a = 1;
    assert(a == [1, 1, 1]);
}


While this is not accepted:

void main() {
    int[] b = new int[3];
    b = 1;
    assert(b == [1, 1, 1]); //Error: cannot implicitly convert expression (1) of type int to int[]
}



I'd like D to require  a[]=1  in that first case too.

I'd like the [] to be required every time an O(n) vector operation is done, for:
- constancy with all other vector operations among two arrays, that require [];
- and to avoid unwanted (and not easy to spot in the code) O(n) operations;
- bugs and confusion in D newbies that don't have memorized all current special cases.

On the other hand Don says that [] is only required for lvalues.

I think this boils to a new table like this:


Rhs is an array, is it compilable?
a       / b             a=b     a[]=b   a=b[]   a[]=b[]
int[3u] / int[3u]       FALSE   true    FALSE   true
int[3u] / int[]         FALSE   true    FALSE   true
int[]   / int[3u]       FALSE   true    FALSE   true
int[]   / int[]         true    true    true    true

Rhs is a element, is it compilable?
a                       a=N     a[]=N   a[0..2]=N
int[3u]                 FALSE   true    true
int[]                   false   true    true


Now if there's a [] on the left, then it's an O(n) vector operation (like a copy), otherwise it's O(1).

That also means:

void main() {
    int[] a = new int[3];
    int[] b = new int[3];    
    a = b; // OK, copies just array fat reference
}

void main() {
    int[3] a, b;
    a = b; // Not OK, hidden vector op
}


I am not sure this new table is fully correct, but it's a start. Fixes of mistakes are welcomes.

-----------------------

This is an alternative proposal.

On the other hand this vector op syntax doesn't currently compile:

void main() {
    int[3] a, b;
    a[] += b;
}


So if array assign is seen as a normal vector op, then the [] is needed on the right too:


Rhs is an array, is it compilable?
a       / b             a=b     a[]=b   a=b[]   a[]=b[]
int[3u] / int[3u]       FALSE   FALSE   FALSE   true
int[3u] / int[]         FALSE   FALSE   FALSE   true
int[]   / int[3u]       FALSE   FALSE   FALSE   true
int[]   / int[]         true    FALSE   FALSE   true

Rhs is a element, is it compilable?
a                       a=N     a[]=N   a[0..2]=N
int[3u]                 FALSE   true    true
int[]                   false   true    true


Where the two cases with dynamic arrays are syntax errors to keep more symmetry:

void main() {
    int[] a = new int[3];
    int[] b = new int[3];
    a[] = b; // error
    a = b[]; // error
}

-----------------------

Lot of time ago I have opened bug issue 3971 on this topic, but that Bugzilla thread contains various mistakes and some parts of it are obsolete.

Bye,
bearophile


More information about the Digitalmars-d mailing list