...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

配列演算を調べてみた - 配列演算(2)

http://d.hatena.ne.jp/haru-s/20080809/1218251206#c
あれっ,配列演算は変数定義と同時には使えないの?


配列演算のことがよくわかってないので仕様を読み直した.

ベクトル演算は、スライス演算子が =, +=, -=, *=, /=, %=, &=, |= 演算子の左辺に来たときに行われます。 その場合の右辺式には、同じ長さと型の配列スライスか、 要素型の値を返す式の、 任意の組み合わせが使用できます。 ベクトル演算に対応している演算子は、 二項演算子 +, -, *, /, %, &, |, と、 単項演算子 -, ~ です。

一応,左辺がスライス演算子のときだよって書いてあるけど,

//(1)
int[] a;
//...
int[] b;
b[] = a[] + 1;

//(2)
int[] a;
//...
int[] b = a[] + 1;

の2つのセマンティクスが違うってのはあんまりじゃね?
それに動的配列の例しか書かれていなくて,静的配列ではどうなのかよくわからない.
あるいは動的配列と静的配列の配列演算はどうなの?
わからないことだらけなので,いつものように,実際にやってみた.

import std.stdio;
void main(){
    int[] a = [1,2,3,4];
    int[4] b = [1,2,3,4];
    
    // 動的配列同士
    {
        // 同じ長さの動的配列同士の配列演算
        int[] r;
        r.length = 4;
        r[] = a[] + 10;
        writefln(r);
        assert(r == [11,12,13,14]);//OK
    }
    {
        // 変数定義と同時に同じ長さの動的配列同士の配列演算
        // 要素数 == 0 のときしか書けないので役に立たないがやってみる
        int[] r = a[0..0] + 10;
        writefln(r);
        //assert(r.length == 0);//それでもNGになっちゃう
    }
    {
        // 変数定義と同時に異なる長さの動的配列同士の配列演算
        int[] r = a[] + 10;// 未定義
        writefln(r);
        //そもそいくらの長さになるべきなのかわかんない
        //assert(r.length == 0);
        //assert(r.length == 4);
    }
    
    // 静的配列同士
    {
        // 同じ長さの静的配列同士の配列演算
        int[4] r;
        r[] = b[] + 10;
        writefln(r);
        assert(r == [11,12,13,14]);//OK
    }
    {
        // 変数定義と同時に同じ長さの静的配列同士の配列演算
        int[4] r = b[] + 10;
        writefln(r);
        assert(r == [11,12,13,14]);//OK
    }
    {
        // 変数定義と同時に異なる長さの静的配列同士の配列演算
        int[3] r_short = b[] + 10;
        writefln(r_short);
        assert(r_short == [11,12,13]);//未定義

        int[5] r_long = b[] + 10;
        writefln(r_long);
        assert(r_long == [11,12,13,14,14]);//未定義
    }

    // 動的配列と静的配列
    {
        // 同じ長さの動的配列と静的配列の配列演算
        int[] r;
        r.length = 4;
        r[] = b[] + 10;
        writefln(r);
        assert(r == [11,12,13,14]);//OK
    }
    {
        // 変数定義と同時に同じ長さの動的配列と静的配列の配列演算
        int[4] r = a[] + 10;
        writefln(r);
        assert(r == [11,12,13,14]);//OK
    }
    {
        // 変数定義と同時に異なる長さの動的配列と静的配列の配列演算
        int[3] r_short = a[] + 10;
        writefln(r_short);
        assert(r_short == [11,12,13]);//未定義
        
        int[5] r_long = a[] + 10;
        writefln(r_long);
        assert(r_long == [11,12,13,14,10]);//未定義
    }
}
/+
[11 12 13 14]
[1 2 3 4 0 0 0 0 0 0]
[1 2 3 4 0 0 0 0 0 0 0 0 9646080 0]
[11 12 13 14]
[11 12 13 14]
[11 12 13]
[11 12 13 14 14]
[11 12 13 14]
[11 12 13 14]
[11 12 13]
[11 12 13 14 10]
+/

結果

というわけで,変数定義と同時かどうかは関係なくて,配列が動的か静的かというのも関係ないらしい.
重要なのは要素数が同じであることのようだ.
ただし,構文上,動的配列の変数定義と同時に配列演算をすると左辺の動的配列の要素数はゼロ以外にできないのだが(だよね?),右辺の配列の要素数がこれと同じ(つまり要素数ゼロ)であっても,まともに動作してない.