配列のnullチェック

返事が遅れましたが、ideoさんからトラバいただきました。ありがとうございます。
h_sakuraiさんからも過分な評価をいただきありがとうございました。

で、以下は 2/22の日記の kurimura さんからのコメントへのお返事(遅い)

array = x[y .. y] とか, array = "" とかのときに
array.ptr!=null && array.length == 0が成立するから,
assert(array.length != 0) にしたほうが無難かも

とのことでした。

array.ptr ではなく、array そのものがnull かどうかを見ているので、
array[x..x] も array = "" も

assert(array != null);

でひっかかりました。

で、これで終わりと思っていたのですが、なにげにyaneuraoさんのページを見ていると、文字列が空かどうかのチェックを、if (str.length == 0) でやるべきか if (str) でやるべきなのかを、Walter Bright さんはじめ多くの方と議論していたのを思い出しました。

それと、そーいや null の判定は if (arr == null) ではなく、if (arr is null) で行うのだったな、ということも思い出しました。

で、以下のようなテンプでテスト。

template max(T) {
  T max(T array) 
    in {
      writefln("array == %s ", array);
      writefln("array.ptr == %0X ", array.ptr);
      writefln("array == null? = " ~
        .toString(cast(bool)(array == null)));
      writefln("array is null? = " ~
        .toString(cast(bool)(array is null)));
      assert(array !is null);
      assert(array != null);
      assert(array.length != 0);
    }
    body {
      T maxValue = array[0];
      foreach (T elm; array) {
        if (maxValue < elm) maxValue = elm;
      }
      return maxValue;
    }
}

unittest {
  {
    writefln("max of slice");
    static int array = [1, 2, 3];
    int maxval = max!(int)(array[1..1]);
    writefln(maxval);
    foreach (int i; array) assert(maxval >= i);
  }

  {
    writefln("max of null string");
    char carr = "";
    char maxval = max!(char)(carr);
    writefln(maxval);
    foreach (char c; carr) assert(maxval >= c);
  }

  writefln("OK unittest of max!(int)()");
}
...
max of slice
array == 
array.ptr == 41509C
array == null? = true
array is null? = false
Error: AssertError Failure array(24)
...
max of null string
array ==
array.ptr == 4150A0
array == null? = true
array is null? = false
Error: AssertError Failure array(24)

ご覧のように(array == null) の結果と、(array is null) の結果が異なっちゃってます。assert でひっかかっている24行目とは、

assert(array != null);

D言語のリファレンスページでは、オブジェクトが null かどうかのチェックは if (obj is null) でやるように書かれていますが、私の場合、上記のように != でやってしまっていたので、length == 0 のときでも、ひっかかったということのようです。

私は、array.length にアクセスする以上、array 自体の null チェックは必須だと思ったのですが、くどく、

char[] carr = null;

とやっても

assert(array.length != 0);

でひっかかってくれました。
kurimuraさんのご指摘どおり、配列の空チェックは、length != 0 で行うのが正しいようです。ありがとうございました。