Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 14974] ファイルの概要

このコミットは、Go言語の実験的なexp/locale/collateパッケージにおける、Unicode文字列の照合(Collation)機能の再構築と、将来的な検索APIの追加に向けた準備を目的としています。主な変更点として、照合要素(collation element)の表現方法の変更(colElemからElemへの型名変更)、照合と検索機能の分離、そして高レベルなオプションAPIの導入が挙げられます。これにより、コードのモジュール化と、ユーザーがより直感的に照合設定を行えるような改善が図られています。

コミット

commit f86ae990e859e026475380f0a1e0c86203d7a0d5
Author: Marcel van Lohuizen <mpvl@golang.org>
Date:   Wed Jan 23 14:15:51 2013 +0100

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/f86ae990e859e026475380f0a1e0c86203d7a0d5

元コミット内容

exp/locale/collate: preparation for adding Search API. Also changed the collate API
further to how (I believe) it will end up being.
It is nicer to separate search from sorting functionality. Collation needs tables that
are not needed by search and vice-versa.  The common functionality is separated out
in the Weigher interface.  As this interface is very low-level, it will be moved to
a sub package (colltab) in a next CL.
The types that will move to this package are Weigher, Elem, and Level.  The addition
of Elem allows for removing some of the duplicate code between collate and collate/build.
This CL also introduces some stubs for a higher-level API for options. The default
proposed options are quite complex and require the user to have a decent understanding
of Unicode collation.  The new options hide a lot of the complexity.

R=rsc
CC=golang-dev
https://golang.org/cl/7058051

変更の背景

このコミットの主な背景は、Go言語のexp/locale/collateパッケージにおけるUnicode文字列の照合機能の改善と拡張です。具体的には以下の点が挙げられます。

  1. 検索APIの追加準備: 将来的に文字列の検索機能(Search API)を導入するにあたり、既存の照合APIの構造を見直す必要がありました。照合と検索は密接に関連していますが、それぞれが異なるデータ構造(テーブル)を必要とするため、機能を分離することでより効率的かつクリーンな設計を目指しています。
  2. APIの再設計: 既存の照合APIは、Unicode Collation Algorithm (UCA) の詳細な知識をユーザーに要求する部分がありました。これをより使いやすく、直感的な高レベルAPIにすることで、ユーザーがUnicode照合の複雑さに深く立ち入ることなく、適切な照合設定を行えるようにする意図があります。
  3. コードの重複排除とモジュール化: collateパッケージとcollate/buildパッケージ間で重複していたコードを削減し、共通の機能をWeigherインターフェースとして分離することで、コードベースの保守性と再利用性を向上させています。特に、colElem型をElem型に統一することで、この重複排除が促進されました。
  4. 低レベル機能の分離: Weigherインターフェースのような低レベルな機能は、より専門的なサブパッケージ(colltab)に移動される予定であり、これによりパッケージの役割分担が明確化されます。

これらの変更は、Go言語の国際化(i18n)サポートを強化し、より堅牢で使いやすい照合・検索機能を提供するための重要なステップです。

前提知識の解説

このコミットを理解するためには、以下の前提知識が役立ちます。

Unicode Collation Algorithm (UCA)

UCAは、Unicode Technical Report #10 (UTR #10) で定義されている、Unicode文字列を言語的に正しい順序でソート(照合)するためのアルゴリズムです。単なるコードポイント順のソートでは、異なる言語や文化における文字の並び順の慣習を反映できません。UCAは、この複雑な要件を満たすために設計されています。

UCAの主要な概念は以下の通りです。

  • 照合要素 (Collation Element: CE): 各文字や文字の組み合わせ(合字など)は、一つ以上の照合要素にマッピングされます。これらの照合要素が、実際の比較の単位となります。
  • 多段階ソート (Multi-level Sorting): UCAは、複数のレベルで比較を行います。
    • Primary Level (第一レベル): 文字の基本的な形状や識別子に基づきます。例えば、'a'と'b'の違い。
    • Secondary Level (第二レベル): アクセント記号やダイアクリティカルマーク(分音記号)の違いに基づきます。例えば、'a'と'ä'の違い。
    • Tertiary Level (第三レベル): 大文字・小文字の違いや、文字の幅(全角・半角)の違いに基づきます。例えば、'a'と'A'の違い。
    • Quaternary Level (第四レベル): 可変要素(variable elements)の扱いに関連し、通常はPrimary Levelの値を再利用して、特定のルール(例: シフトされた重み付け)を適用します。これは、句読点や記号などの扱いを制御するために使用されます。
  • ソートキー (Sort Key): UCAは、文字列を比較可能なバイト列(ソートキー)に変換します。このソートキーをバイナリ比較することで、UCAのルールに従った文字列の順序を決定できます。

LDML (Locale Data Markup Language)

LDMLは、Unicode Consortiumによって定義されたXMLベースのフォーマット(UTS#35)で、ロケールデータ(言語、地域、通貨、日付、時刻、数値の書式設定、照合ルールなど)を表現するための標準です。LDMLは、Unicode Common Locale Data Repository (CLDR) の基盤となっており、国際化されたソフトウェアの開発において、地域ごとの慣習やルールを統一的に扱うために不可欠です。

照合ルールもLDMLの一部として定義されており、特定の言語や地域における文字の並び順のカスタマイズを可能にします。

exp/locale/collateパッケージの文脈

Go言語のexpディレクトリは、実験的なパッケージや将来的に標準ライブラリに取り込まれる可能性のあるパッケージを置く場所です。exp/locale/collateは、Go言語におけるUnicode照合機能の初期実装または実験的なバージョンでした。このコミットが行われた2013年時点では、まだ開発途上にあり、その後のGo言語の進化に伴い、このパッケージの機能はgolang.org/x/text/collateとしてより成熟した形で提供されるようになりました。したがって、このコミットは、現在のgolang.org/x/text/collateパッケージの基礎を築く重要なステップの一つと見なすことができます。

技術的詳細

このコミットは、exp/locale/collateパッケージの内部構造にいくつかの重要な変更を加えています。

  1. colElemからElemへの型名変更と役割の明確化:

    • 以前はcolElemという型が照合要素を表していましたが、このコミットでElemに名称が変更されました。これは、より汎用的な「要素」としての役割を強調し、照合だけでなく検索など他の機能でも利用されることを示唆しています。
    • Elem型には、Primary(), Secondary(), Tertiary(), Quaternary(), CCC() (Canonical Combining Class), Mask()などのメソッドが追加され、照合要素の各レベルの重みや特性をより明確に取得・操作できるようになりました。
    • MakeElem, MakeQuaternaryといったコンストラクタ関数も導入され、Elemの生成がより構造化されています。
  2. Weigherインターフェースの導入:

    • colltab.goという新しいファイルが追加され、Weigherインターフェースが定義されました。このインターフェースは、文字列から照合要素(Elem)を生成する低レベルな機能(AppendNext, AppendNextStringなど)を抽象化します。
    • コミットメッセージにあるように、このインターフェースは「非常に低レベル」であり、将来的にcolltabというサブパッケージに移動される予定です。これにより、照合テーブルの具体的な実装と、それを利用する高レベルな照合ロジックが分離されます。
  3. Collator構造体の変更とAPIの簡素化:

    • Collator構造体から、直接的な*tableフィールドが削除され、代わりにWeigherインターフェース型のtフィールドが導入されました。これにより、Collatorは具体的な照合テーブルの実装に依存せず、Weigherインターフェースを介して照合要素を取得するようになります。
    • CollatorSetOptionsメソッドが導入され、Numeric, IgnoreCase, IgnoreDiacriticsなどの高レベルなオプションをまとめて設定できるようになりました。これにより、ユーザーはUCAの複雑なレベル設定を直接操作することなく、一般的な照合要件を満たすことができます。
    • Level型(Primary, Secondary, Tertiary, Quaternary, Identity)がcollate.goからcolelem.goに移動され、照合要素のレベルとより密接に関連付けられました。
  4. 内部処理の変更:

    • iter構造体(文字列を走査して照合要素を生成するイテレータ)の内部も変更され、colElemの代わりにElemを使用するようになりました。また、setInputsetInputStringメソッドから*Collator引数が削除され、より独立した動作が可能になっています。
    • table.go内のappendNext関数もElem型を扱うように変更され、source構造体も導入されて文字列とバイト列の処理を抽象化しています。

これらの変更は、Go言語の照合パッケージが、よりモジュール化され、拡張性があり、かつユーザーフレンドリーなAPIを提供する方向へと進化していることを示しています。特に、低レベルな照合要素の処理と高レベルな照合ロジックの分離は、今後の機能追加(特に検索API)やパフォーマンス最適化において重要な基盤となります。

コアとなるコードの変更箇所

このコミットにおけるコアとなるコードの変更箇所は以下のファイルに集中しています。

  • src/pkg/exp/locale/collate/colelem.go:

    • colElem型がElem型にリネームされました。
    • Level型がcollate.goからこのファイルに移動されました。
    • Elem型にPrimary(), Secondary(), Tertiary(), Quaternary(), CCC(), Mask(), Weight()などのメソッドが追加されました。
    • MakeElem, MakeQuaternaryといった新しいコンストラクタ関数が追加されました。
    • 定数maxQuaternaryMaxQuaternaryにリネームされました。
  • src/pkg/exp/locale/collate/collate.go:

    • Level型の定義が削除され、colelem.goに移動されました。
    • Collator構造体のt *tableフィールドがt Weigherインターフェース型に変更されました。
    • SetOptionsメソッドとOption型が追加され、高レベルな照合オプションを設定できるようになりました。
    • NewFromTable関数が追加され、Weigherインターフェースを受け取るようになりました。
    • Collatoriterフィールドの型がcolElemからElemに変更されました。
    • keyFromElems関数が[]colElemの代わりに[]Elemを受け取るようになりました。
    • processWeights関数も[]colElemの代わりに[]Elemを受け取るようになりました。
  • src/pkg/exp/locale/collate/colltab.go (新規ファイル):

    • Weigherインターフェースが定義されました。このインターフェースは、照合要素の生成に関する低レベルな操作を抽象化します。
  • src/pkg/exp/locale/collate/table.go:

    • table構造体がWeigherインターフェースを実装するようになりました。
    • AppendNext, AppendNextString, Start, StartString, DomainといったWeigherインターフェースのメソッドが追加されました。
    • 内部のappendNext, appendExpansion, matchContraction, matchContractionString関数がcolElemの代わりにElemを扱うように変更されました。
    • source構造体が定義され、文字列とバイト列の処理を抽象化しました。
  • src/pkg/exp/locale/collate/trie.go:

    • lookupValue, lookup, lookupString関数がcolElemの代わりにElemを返すように変更されました。
  • src/pkg/exp/locale/collate/colelem_test.go:

    • テストコード内のcolElem型がElem型に更新されました。

コアとなるコードの解説

Elem型への変更と照合要素の操作

最も根本的な変更は、照合要素を表す型がcolElemからElemにリネームされたことです。これは単なる名称変更以上の意味を持ちます。Elem型には、Unicode Collation Algorithm (UCA) の各レベル(Primary, Secondary, Tertiary, Quaternary)に対応する重みを取得するためのメソッド(Primary(), Secondary(), Tertiary(), Quaternary())が追加されました。これにより、照合要素の内部表現を直接操作することなく、よりセマンティックな方法で各レベルの重みにアクセスできるようになります。

例えば、以前はce.primary()のように直接フィールドにアクセスしていた箇所が、ce.Primary()というメソッド呼び出しに変わっています。これは、オブジェクト指向的なアプローチを強化し、将来的な内部実装の変更に対する柔軟性を提供します。

また、MakeElemMakeQuaternaryといったファクトリ関数が導入されたことで、Elemオブジェクトの生成がより安全かつ意図的に行えるようになりました。

Weigherインターフェースによる機能分離

colltab.goで定義されたWeigherインターフェースは、このコミットの設計思想の中心です。このインターフェースは、入力文字列から照合要素のシーケンスを生成する低レベルなロジックを抽象化します。

type Weigher interface {
	Start(p int, b []byte) int
	StartString(p int, s string) int
	AppendNext(buf []Elem, s []byte) (ce []Elem, n int)
	AppendNextString(buf []Elem, s string) (ce []Elem, n int)
	Domain() []string
}

Collator構造体は、具体的な照合テーブルの実装(*table)を直接持つ代わりに、このWeigherインターフェースを実装するオブジェクトを持つようになりました。これにより、Collatorは「どのように照合要素が生成されるか」という詳細から切り離され、「生成された照合要素をどのように比較するか」という高レベルなロジックに集中できるようになります。

この分離は、将来的に異なる照合テーブルの実装(例: 特定の言語に特化したテーブル、よりコンパクトなテーブルなど)を容易にプラグインできるようにするための重要なステップです。また、コミットメッセージにあるように、照合と検索で共通する低レベルな機能がWeigherとして抽出されたことで、コードの再利用性が向上し、それぞれの機能が独立して進化できるようになります。

Collator.SetOptionsによる高レベルAPIの提供

Collator構造体に追加されたSetOptionsメソッドとOption型は、ユーザーエクスペリエンスの向上を目的としています。

type Option int

const (
	Numeric          Option = 1 << iota // Sort numbers numerically ("2" < "12").
	IgnoreCase                          // Case-insensitive search.
	IgnoreDiacritics                    // Ignore diacritical marks. ("o" == "ö").
	IgnoreWidth                         // Ignore full versus normal width.
	UpperFirst                          // Sort upper case before lower case.
	LowerFirst                          // Sort lower case before upper case.
	Force                               // Force ordering if strings are equivalent but not equal.

	Loose = IgnoreDiacritics | IgnoreWidth | IgnoreCase
)

func (c *Collator) SetOptions(o Option) {
	// TODO: implement
}

以前のAPIでは、ユーザーがUCAのPrimary, Secondary, Tertiaryといったレベルを直接操作して照合の挙動を制御する必要がありました。これは強力ですが、Unicode照合の専門知識がないユーザーにとっては複雑でした。SetOptionsは、Numeric(数値ソート)、IgnoreCase(大文字・小文字を無視)、IgnoreDiacritics(アクセント記号を無視)といった、より直感的で一般的な照合オプションを提供します。

これにより、ユーザーは「大文字・小文字を区別しないソート」や「アクセント記号を無視したソート」といった具体的な要件を、UCAの内部的なレベル構造を意識することなく設定できるようになります。これは、APIの使いやすさを大幅に向上させる変更です。

これらの変更は全体として、exp/locale/collateパッケージが、より堅牢で、モジュール化され、かつユーザーフレンドリーな国際化機能を提供するための基盤を築いていることを示しています。

関連リンク

参考にした情報源リンク