激しく疑問である。
UAX#15によると、compatibility decompositionを適用した結果、全角濁点(0x309b)は、半角スペース(0x20)+半角濁点(0x3099)に置き換えられる。だから、たとえば「タ゛」(0x30bf 0x309b)は0x30bf 0x20 0x3099となる。
これって既に「ダ」(0x30c0)をcompatibility decomposeした結果(0x30bf 0x3099)と同一視できなかったりする。
さらに、全角濁点を使っていた方は、これをcompositionで元に戻そうとしても、0x20が邪魔で、「ダ」(0x30c0)に戻すことができない。0x20が除去されるルールは(少なくともUAX#15 revision 25には)存在しない(するわけがないと思う)。0x20はどうやらUnicode 1.xの頃から含まれていたようだ。
私見としては、0x20などをcompatibility mappingに含めているUnicodeData.txt sucksということなのだけど、どうでしょう。1 とりあえずこんなところで仕様の問題でハマって時間くってもーた。
追記: ていうか別に同一でない文字列としてもいいんじゃん?と考えることもできそうだけど、UAX#15のA1.3 Normalization Forms KD and KC Examplesでは、NFKCではこれらは同一の文字列になる、と明言してしまっているのよね。というかそもそもそこが疑問の出発点だったわけでして。
コメント
batta — 07/20/2007 11:48:53
むしろハゲシク逆で、0x20はNFKでこの2つを同一視させない
ように挿入されているようなものです。
たとえば 00DC が、0055 00A8 と一緒にされたら困るような
もの。そもそも半角カタカナで濁音を別文字扱いするという、
例外(縦書き考えると変でしょ?)を真面目に全角にも
適用しようとするからこういう罠にはまるのかな?
atsushieno — 07/20/2007 13:03:23
ええと、combining(U+3099)とnon-combining(U+309B)を混同していたのが↑のように書いた理由なので、U+309Bについては0x20がNFKC/NFKDで同一視を防ぐ意図で追加されていることは(現在では)分かります。
non-combiningであればすべからく同一視を防ぐべし、という設計意図(があるんですよね?)があることは、もっと後になって気付きました。
Footnotes
-
何を言ってるのか分からないYO!という人は、.NET 2.0にあるString.Normalize()で「ダ」と「タ゛」をNormalizationForm.FormKCで正規化して比較してみましょう。 ↩