Array slice assign syntax

Martin Nowak dawg at dawgfoto.de
Thu Nov 17 00:12:19 PST 2011


On Wed, 16 Nov 2011 19:47:47 +0100, Timon Gehr <timon.gehr at gmx.ch> wrote:

> On 11/16/2011 04:24 AM, bearophile wrote:
>> 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
>
> First thing:
>
> int[3] a=3; // kill it!!
>
> Rest:
>
> a[] is _just a shortcut_ for a[0..$]! Are you really suggesting to  
> disallow slicing?
>
>
> You are thinking too much in terms of syntax and not enough in terms of  
> semantics.
>
> They are basically two distinct things involved here:
>
> 1. static arrays and lvalue slices
> 2. dynamic arrays and rvalue slices
>
> 1 implies value semantics, 2 implies reference semantics, where value  
> semantics overrides reference semantics.
>
> Any other distinction is more or less arbitrary. As you pointed out, the  
> main indicator of distinction is value vs reference semantics of the  
> performed assignments.
>
> We certainly agree on this:
>
> Rhs is an array, is it compilable?
> a       / b             a=b     a[]=b   a=b[]   a[]=b[]
> int[3u] / int[3u]       ?       ?       ?       true
> int[3u] / int[]         ?       ?       ?       true
> int[]   / int[3u]       ?       ?       ?       true
> int[]   / int[]         ?       ?       ?       true
>
>
> Now, a dynamic array a is equivalent to a[], and a static array b is  
> equivalent to an lvalue slice b[]=.
>
> This gives the following equivalence classes of operations:
>
> Rhs is an array, is it compilable?
> a       / b             a=b     a[]=b   a=b[]   a[]=b[]
> int[3u] / int[3u]       1       1       2       2
> int[3u] / int[]         2       2       2       2
> int[]   / int[3u]       3       1       4       2
> int[]   / int[]         4       2       4       2
>
> Any of the same class should behave the same.
>
> Now, you suggest in both proposals to allow at least one of class 2 and  
> at least one of class 4. Filling all those out delivers:
>
> Rhs is an array, is it compilable?
> a       / b             a=b     a[]=b   a=b[]   a[]=b[]
> int[3u] / int[3u]       (1)     (1)     true    true
> int[3u] / int[]         true    true    true    true
> int[]   / int[3u]       (3)     (1)     true    true
> int[]   / int[]         true    true    true    true
>
> 1 is "assign value to value". 3. is "assign value to reference".
>
> The upper left corner should certainly be true, values of any mutable  
> type should be able to be assigned to themselves.
>
>
> This leaves:
>
> 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]       (3)     true    true    true
> int[]   / int[]         true    true    true    true
>
>
> 3 is the odd thing out. Now let's think about it, what should:
>
> int[] a;
> int[3] b;
>
> a=b;
>
> do?
>
> The answer is, there are two options.
>
> 1. implicitly slice b
> 2. copy b by value into a
>
No there are not, a owns no storage to hold values, it is only a slice.
In that case a should be be a slice of the static array b.
It could make sense to require b[] for the conversion, but copying is no  
option.

> One is as arbitrary as the other, so it should be disallowed in a sane  
> design. Which leaves:
>
> 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]       FALSE   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]                 FALSE   true    true
> int[]                   false   true    true
>
>
> And that is how it should be.
>
>
>
>
>
>


More information about the Digitalmars-d mailing list