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

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

コミット

このコミット f38da96755cea4fde703b4601d5959150587eab4 は、Go言語の実験的なロケールパッケージ exp/locale/collate における低レベルの照合(collation)機能を、colltab という独立したパッケージに移動させるものです。これにより、照合機能が search パッケージなど他のパッケージと共有される際に、それぞれのパッケージが同じテーブルを使用する必要がなくなり、モジュール間の結合度が低減されます。

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

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

元コミット内容

exp/locale/collate: moved low-level collation functionality
into separate package.  This allows this code to be shared
with the search package without the need for these two to use
the same tables.
Adjusted various files accordingly.

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

変更の背景

この変更の主な背景は、Go言語の実験的なロケールパッケージ exp/locale/collate が提供する低レベルの照合機能を、より広範な用途で再利用可能にすることです。具体的には、search パッケージのような他のパッケージが照合機能を利用する際に、collate パッケージが内部的に使用するデータテーブルに依存することなく、独立して機能を利用できるようにすることが目的です。

従来の設計では、collate パッケージ内の低レベル機能とデータテーブルが密接に結合しており、これが他のパッケージでの再利用を妨げていました。この結合を解消することで、collate パッケージは高レベルの照合ロジックに集中し、低レベルのデータ構造やアルゴリズムは colltab パッケージが担当するという、よりクリーンなアーキテクチャが実現されます。これにより、将来的に異なる照合テーブルやアルゴリズムを導入する際の柔軟性も向上します。

前提知識の解説

照合(Collation)

照合とは、文字列を特定の順序で並べ替える(ソートする)プロセスです。これは単なる文字コードの比較ではなく、言語や文化に特有のルール(例: アクセント記号の有無、大文字・小文字の区別、特定の文字の並び順など)に基づいて行われます。例えば、ドイツ語では 'ä' は 'a' の後に来ることがありますが、スウェーデン語では 'z' の後に来ることがあります。

Unicode Collation Algorithm (UCA)

Unicode Collation Algorithm (UCA) は、Unicode Consortiumによって定義された、多言語対応の照合のための標準アルゴリズムです。UCAは、文字列を比較するために「照合要素(Collation Elements)」と呼ばれる数値のシーケンスに変換します。これらの照合要素は、通常、プライマリ、セカンダリ、ターシャリ、クォータナリの4つのレベルの重み(weights)を持ちます。

  • プライマリ(Primary): 文字の基本的な形状に基づいた重み。例えば、'a' と 'A' は同じプライマリ重みを持ちます。
  • セカンダリ(Secondary): アクセント記号やダイアクリティカルマークに基づいた重み。例えば、'a' と 'á' は異なるセカンダリ重みを持ちます。
  • ターシャリ(Tertiary): 大文字・小文字の区別や、半角・全角などのバリアントに基づいた重み。例えば、'a' と 'A' は異なるターシャリ重みを持ちます。
  • クォータナリ(Quaternary): 可変要素(variable elements)の処理に使用される重み。句読点や記号など、通常は無視される文字の順序を決定するために使用されます。

Go言語の exp パッケージ

Go言語の標準ライブラリには、exp というプレフィックスを持つパッケージが存在します。これらは「実験的(experimental)」なパッケージであり、まだ安定版としてリリースされていない機能やAPIが含まれています。これらのパッケージは、将来的に標準ライブラリに組み込まれる可能性がありますが、APIが変更されたり、削除されたりする可能性もあります。

Go言語のパッケージ構造とインポート

Go言語では、コードはパッケージに分割されます。パッケージはディレクトリ構造に対応し、他のパッケージの関数や型を使用するには import ステートメントで明示的にインポートする必要があります。例えば、exp/locale/collate パッケージ内の型や関数を使用するには import "exp/locale/collate" と記述します。このコミットでは、exp/locale/collate パッケージが exp/locale/collate/colltab パッケージに依存するように変更されています。

技術的詳細

このコミットの技術的な核心は、Go言語のパッケージ分割と依存関係の再構築にあります。

  1. 新パッケージ colltab の導入: src/pkg/exp/locale/collate/ ディレクトリ内に存在していた、照合の低レベルなデータ構造やアルゴリズム(例: 照合要素の表現、Trie構造、テーブルの初期化など)を扱うファイル群が、新たに作成された src/pkg/exp/locale/collate/colltab/ ディレクトリに移動されました。これにより、colltab は照合テーブルの内部表現と、それらを操作するための基本的な機能を提供する独立したパッケージとなります。

  2. ファイルのリネームと移動: 以下のファイルが collate パッケージから colltab パッケージへ移動し、パッケージ名が collate から colltab に変更されました。

    • colelem.go
    • colelem_test.go
    • colltab.go (このファイル自体が colltab パッケージのインターフェースを定義する中心的なファイルとなる)
    • contract.go
    • contract_test.go
    • export.go
    • table.go
    • trie.go
    • trie_test.go
  3. インポートパスの更新: collate パッケージ内のファイルや、collate パッケージに依存していた他のファイル(例: build パッケージ内のファイル、collate_test.go など)では、移動された機能や型を参照するためにインポートパスが exp/locale/collate から exp/locale/collate/colltab へと変更されました。例えば、collate.Levelcollate.Elem といった型は、colltab.Levelcolltab.Elem として参照されるようになります。

  4. collate.Collator の変更: collate.Collator 構造体は、直接 colltab.Weigher インターフェースを実装する型(colltab.table など)を参照するように変更されました。これにより、Collator は低レベルの実装詳細から切り離され、colltab パッケージが提供する抽象化されたインターフェースを通じて照合データにアクセスするようになります。

  5. MakeElem 関数の移動と利用: 照合要素(Collation Element)を作成する makeCE 関数(build/colelem.go にあった)のロジックが、colltab/colelem.go 内の MakeElem 関数として再実装されました。これにより、照合要素の生成ロジックが低レベルパッケージに集約され、build パッケージからは colltab.MakeElem を呼び出す形に変更されました。

  6. index.go の新規追加: src/pkg/exp/locale/collate/index.go が新規追加されました。このファイルは、照合テーブルのインデックス情報(tableIndex 構造体)を定義し、colltab パッケージが提供する低レベルのデータにアクセスするための橋渡しをします。

この変更により、collate パッケージは高レベルの照合APIとロジックを提供し、colltab パッケージは照合データの内部表現と基本的な操作に特化するという、明確な役割分担が実現されました。これにより、colltab パッケージは collate パッケージだけでなく、search パッケージなど他のGoパッケージからも独立して利用できるようになり、コードの再利用性と保守性が向上します。

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

このコミットにおけるコアとなるコードの変更は、主に以下の2点に集約されます。

  1. インポートパスの変更: src/pkg/exp/locale/collate/build/builder.go の例を見ると、import "exp/locale/collate"import "exp/locale/collate/colltab" に変更されています。

    --- a/src/pkg/exp/locale/collate/build/builder.go
    +++ b/src/pkg/exp/locale/collate/build/builder.go
    @@ -5,7 +5,7 @@
     package build
    
     import (
    -"	exp/locale/collate"
    +"	exp/locale/collate/colltab"
     	"exp/norm"
     	"fmt"
     	"io"
    
  2. 型参照の変更: 上記インポートパスの変更に伴い、collate パッケージで定義されていた型(例: collate.Level)が、新しく移動された colltab パッケージの型(例: colltab.Level)に置き換えられています。

    src/pkg/exp/locale/collate/build/builder.goInsert メソッドのシグネチャの変更がその一例です。

    --- a/src/pkg/exp/locale/collate/build/builder.go
    +++ b/src/pkg/exp/locale/collate/build/builder.go
    @@ -225,25 +225,25 @@ func (t *Tailoring) SetAnchorBefore(anchor string) error {
     // at the primary sorting level:
     //      t := b.Tailoring("se")
     // 	\t\tt.SetAnchor("z")
    -// 	\t\tt.Insert(collate.Primary, "ä", "")
    +// 	\t\tt.Insert(colltab.Primary, "ä", "")
     // Order "ü" after "ue" at the secondary sorting level:
     //\t\tt.SetAnchor("ue")
    -//\t\tt.Insert(collate.Secondary, "ü","")
    +//\t\tt.Insert(colltab.Secondary, "ü","")
     // or
     //\t\tt.SetAnchor("u")
    -//\t\tt.Insert(collate.Secondary, "ü", "e")
    +//\t\tt.Insert(colltab.Secondary, "ü", "e")
     // Order "q" afer "ab" at the secondary level and "Q" after "q"
     // at the tertiary level:
     // 	\t\tt.SetAnchor("ab")
    -// 	\t\tt.Insert(collate.Secondary, "q", "")
    -// 	\t\tt.Insert(collate.Tertiary, "Q", "")
    +// 	\t\tt.Insert(colltab.Secondary, "q", "")
    +// 	\t\tt.Insert(colltab.Tertiary, "Q", "")
     // Order "b" before "a":
     //      t.SetAnchorBefore("a")
    -//      t.Insert(collate.Primary, "b", "")
    +//      t.Insert(colltab.Primary, "b", "")
     // Order "0" after the last primary ignorable:
     //      t.SetAnchor("<last_primary_ignorable/>")
    -//      t.Insert(collate.Primary, "0", "")
    -+func (t *Tailoring) Insert(level collate.Level, str, extend string) error {
    ++func (t *Tailoring) Insert(level colltab.Level, str, extend string) error {
     	if t.anchor == nil {
     		return fmt.Errorf("%s:Insert: no anchor point set for tailoring of %s", t.id, str)
     	}
    

    同様に、src/pkg/exp/locale/collate/collate.go では、Collator 構造体の Strength フィールドの型が Level から colltab.Level に変更されています。

    --- a/src/pkg/exp/locale/collate/collate.go
    +++ b/src/pkg/exp/locale/collate/collate.go
    @@ -46,7 +47,7 @@ type Collator struct {
     // diacritical marks to be ignored but not case without having to fiddle with levels).
    
     // Strength sets the maximum level to use in comparison.
    -	Strength Level
    +	Strength colltab.Level
    
     // Alternate specifies an alternative handling of variables.
     	Alternate AlternateHandling
    

コアとなるコードの解説

このコミットの主要な目的は、照合機能の低レベルな部分を colltab という新しいパッケージに分離し、exp/locale/collate パッケージがその高レベルなインターフェースとして機能するようにすることです。

上記のコード変更箇所は、この分離がどのように行われたかを示しています。

  1. import "exp/locale/collate/colltab": これは、exp/locale/collate パッケージ内のファイルが、新しく作成された colltab パッケージの機能を利用するために必要な変更です。Go言語では、他のパッケージの公開された(エクスポートされた)識別子(関数、変数、型など)を使用するには、そのパッケージをインポートする必要があります。この変更により、collate パッケージは colltab パッケージに依存するようになります。

  2. collate.Level から colltab.Level への変更: Level 型は、照合の比較レベル(プライマリ、セカンダリ、ターシャリなど)を定義する列挙型です。この型が colltab パッケージに移動されたため、collate パッケージやその関連パッケージ(build など)で Level を参照する際には、colltab.Level という完全修飾名を使用する必要があります。これは、Go言語におけるパッケージ間の依存関係と、識別子のスコープの基本的なルールに従った変更です。

    例えば、Tailoring 構造体の Insert メソッドのシグネチャが func (t *Tailoring) Insert(level collate.Level, str, extend string) error から func (t *Tailoring) Insert(level colltab.Level, str, extend string) error に変更されたのは、Level 型が colltab パッケージに移動したためです。同様に、collate.Primarycollate.Secondary といった定数も、colltab.Primarycolltab.Secondary に変更されています。

これらの変更は、照合ロジックの低レベルな実装詳細を colltab パッケージにカプセル化し、collate パッケージはより高レベルな照合APIを提供するという、明確な責任分担を確立します。これにより、collate パッケージのコードはより簡潔になり、colltab パッケージは他のGoパッケージからも独立して再利用可能なコンポーネントとして機能できるようになります。これは、Go言語における良いパッケージ設計の原則(単一責任の原則、疎結合など)に沿った改善と言えます。

関連リンク

参考にした情報源リンク