Hatena::ブログ(Diary)

Cafe Babe RSSフィード

2011-01-19

[] 「Java 6 でIVS比較すると何が起こるか」の記事の誤り(続編)

先日のエントリで「ざっとチェックした限りでは,それらにはまだIVSがらみの変更はないようだが,もし見落としがあれば教えて頂きたい」と書いておいたら,さっそく仕様書記述はないが,Unicode DatabaseのDUCET(Default Unicode Collation Element Table)はすでに変更されていると指摘して頂いた.どうもありがとう.

DUCETをチェックしなかったのは,「Unicode Collation Algorithm」でjava.text.Collatorクラスjava.text.RuleBasedCollatorクラス引用されているように,Mark Davisjava.textパッケージ設計に直接関わっていて,Unicode Databaseがそのままjava.textパッケージに使われていると思っていたからだが,指摘されて実はjava.text.Collatorクラスの実装では,ロケールごとに照合規則を定義して,それをロードしていることを思い出した.

以下が現在のままでも正しく動くコードである

import java.text.Collator;
import java.text.RuleBasedCollator;

public class VariationSelectorTest {
    public static void main(String[] args) throws Exception {
	String nonIvs = "与太郎";
	String ivs1 = "与\uDB40\uDD00太郎";
	String ivs2 = "与\uDB40\uDD02太郎";
	String nonIvsNext = "与那国";

	RuleBasedCollator c = new RuleBasedCollator(",\uDB40\uDD00 ,\uDB40\uDD02 " + ((RuleBasedCollator)Collator.getInstance()).getRules());
	c.setStrength(Collator.PRIMARY);

	System.out.println("Compare " + ivs1 + " with " + nonIvs + ": " +
			   c.compare("test", "test\t"));
	System.out.println("Compare " + ivs1 + " with " + nonIvs + ": " +
			   c.compare(ivs1, nonIvs));
	System.out.println("Compare " + ivs1 + " with " + ivs2 + ": " +
			   c.compare(ivs1, ivs2));
	System.out.println("Compare " + nonIvs + " with " + nonIvsNext + ": " +
			   c.compare(nonIvs, nonIvsNext));
	System.out.println("Compare " + nonIvsNext + " with " + ivs1 + ": " +
			   c.compare(nonIvsNext, ivs1));
    }
}

このコードポイントは以下の通りだ.

  • setStrength()で照合の強さを指定している.
  • デフォルトの照合規則に,異体字選択子を無視する(このコードで対象とする最低限の)規則を追加している.

RuleBasedCollatorは正しく動作するが,デフォルトの照合規則に入っていないのが問題なので,それはバグレポートして修正要求するとよいだろう.

なお,面白いことにApache HarmonyのRuleBasedCollatorの実装コメントには,「If a character is not located in the RuleBasedCollator, the default Unicode Collation Algorithm (UCA) rulebased table is automatically searched as a backup.」と書かれているので,こちらでは正しく動くかもしれない(未確認).

なお,Togetterでは,照合よりも正規化の話が進行していたのだが,現在の正規化方法ではまだ区別されてしまうという理解でよいのだろうか?(確かにテストコードは,そのように動くのだが…)

えむけいえむけい 2011/01/21 19:31 > java.text.Collatorクラスの実装では,ロケールごとに照合規則を定義して,それをロードしていることを思い出した.

CLDR root localeにもVSを無視する規則はとっくの昔に入ってる(というか昔のCLDRではDUCETそのものだった)ので、Javaのロケール別データがどのように作られてるのか知りませんが、ショボいことに違いはありません。CLDRのロケール別データはroot localeに対する最小差分しか含まれていない(とCLDRのページにきっぱり書かれている)ので、CLDRを使っているのにroot localeのデータを使っていないとしたらJavaのCollatorはやはりバグっています。

> 現在の正規化方法ではまだ区別されてしまう

IVSを正規化で削除してしまったら(安岡先生の要望のように)区別したくなってもできなくて困ると思うんですが。UCAは最初に入力テキストをNFDで正規化しますから。本当にUTS #10読んでますか? 正規分解ではなく互換分解でのみ削除されるようにしろということですか?
現にJavaのRuleBasedCollatorで互換漢字を区別することはできません(規則を追加しようとした時点で"A character can't be unequal to itself."というメッセージの例外が投げられました)。
AppleがModified NFDを標準化しようとして却下された前歴もあるので、今さらNormalizeの規則変更が受理されるとも思えません。基本的にCollationで対応すべきでしょう。

ところでDUCETの末尾にはなぜかU+2F800あたりの互換漢字に関する定義が入ってますが、これはどういうときに使われるんでしょうか? 謎です。

えむけいえむけい 2011/01/21 22:43 ・分解マッピングは文字に対して定義されるものなので、IVS(列)に対して定義することはできません。また1文字以上に分解されなければならないので、IVS(文字)に対して0文字への分解マッピングも定義できません。
・合成がIVS→基底文字となるような分解マッピングは一意に定まらないので定義不可能です。
・合成には正規合成しかありません。正規合成を変更したら正規化の安定性に違反します。正規化の安定性を前提に設計されたあらゆるもの(ほんの一例を挙げればDUCETやCLDRのCollation Data)に誤動作のおそれがあります。
> Togetterでは,照合よりも正規化の話が進行していたのだが,
はっきり言ってIVSの同一視から正規化の話になること自体理解に苦しみます(それも小形氏、川幡氏、直井氏、狩野氏という面々が揃っていながら)。とくにJIS2004の字形変更にすらあれだけ反対していたはずの小形氏が「なるほど、説得力ありますね」とか、小形氏じゃなければ正気を疑いたくなります。

えむけいえむけい 2011/01/22 22:41 UAX #15を見たらCompatibility Compositesという用語が使われていたので3番目は撤回します。IVS→基底文字の互換合成がそもそも定義不可能であることに変わりはないのでこんなのは些細なことですから。
基底文字が互換合成だと、VSの基底文字は分解可能な文字であってはならないという規則にも違反します。

えむけいえむけい 2011/01/23 15:50 > 「Unicode Collation Algorithm」でjava.text.Collatorクラスとjava.text.RuleBasedCollatorクラスが引用されているように,

最新版のUCAでも確かにReferencesの章に残っていることはいますが、
http://www.unicode.org/reports/tr10/#JavaCollator
この[JavaCollator]は本文のどこからも参照されていません。それどころか
> A simpler version of this syntax is also used in Java, although at the time of this writing, Java does not implement the UCA.
と書かれています。
http://www.unicode.org/reports/tr10/#Tailoring_Example

LDMLの仕様でも、
> Java uses an early version of the basci collation syntax, but has not been updated recently. It does not support any of the basic syntax marked with [...], and its default table is not the UCA.
と書かれています。
http://www.unicode.org/reports/tr35/#Collation_Elements

UTS #10をgrep程度以上に読んでいない(あるいは大昔に一度読んだきりまったく読んでいない)ということはよくわかりました。

実際、[...]構文をサポートしていないのでU+E0100..U+E01EFをignorableにしようと思ったらRuleBasedCllatorに渡すルールの先頭に書かなければならないとか、ルールを連結するとき(Javadocに書かれているのとは裏腹に)単純に連結するだけではignorableな文字のルールが壊されてうまくいかないので'<'を検索しなければならない(しかもエスケープを考慮する必要があるので単純なindexOfではうまくいかない)とか、不便で仕方ありません。

前のエントリでおっしゃってるように
> その場合には,私もJava,C#,ECMAScriptの仕様策定や標準化に関わってきたので,何らかの協力ができるかもしれない.
ならこの腐った仕様を一刻も早くどうにかしてほしいですね。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/kazama/20110119/p1