配列の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 で行うのが正しいようです。ありがとうございました。