IndexOf() - unstable algorithm
expansionに大ハマりです。
今、こんなAPIがあるとします。まあCompareInfoなんですけど。
で、引数に"\u00E6"を渡すことを考えます。ちなみにU+E6はaとeの合字です。なので、
int IndexOf (string source, string target)
は5を返します。じゃあ問題。↓は何を返すべきでしょうか?
IndexOf ("01234\u00E6", "ae")
IndexOf ("ABC\u00E6", "e")
U+E6はaとeの合字だから、ABCaの次だから…4?? そんなわけありません。戻り値はあくまでsourceのインデックスを返さなければならないはずです。
ちなみに.NETのCompareInfoは-1を返します。なるほど、それはアリなのか。そう思って↓をやってみると
IndexOf ("ABC\u00E6", "a")
これは3を返したりして。もうワケが分かりません。
ええと、1文字分以上のsortkeyの配列定義もつ1つ以上のcharの順列を「文字要素」と定義すると、たぶんIndexOf()は、対象となるtargetの先頭の文字要素にマッチする文字要素を包含する文字要素*1のインデックスを返すべきなのかな、と思う。つまりIndexOf("ABC\u00E6", "e")は"a"と同じ3を返すべきじゃないかな、と思う。
ただし、その設計では、IndexOf(s, t)の戻り値nについてIsPrefix(s, t, n, s.Length - n)が必ずしも成立しない、という問題がある。これは特にIndexOf()を実装する側が内部的にこのIsPrefix()を用いることが出来ないので辛い。同様に、一体どういう処理ならばこの戻り値を適切に利用できるのかという疑問が常につきまとう。
結局IndexOf()っていう機能自体が、intを返すなんていうお手軽なAPIで実装できるほど簡単なものではないはずなのだ。
*1:あーややこし。ここが「文字」ではなく「文字要素」なのは、source側のcharが常にchar1つとは限らないため