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

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

このコミットは、Go言語の標準ライブラリbytesパッケージ内のExampleCompare_search関数の例を修正するものです。具体的には、sort.Search関数を使用する際のbytes.Compareの利用方法が、sort.Searchの一般的な慣習と一貫性を持つように変更されています。

コミット

bytes: Change Compare example to be consistent with sort.Search's.

R=rsc, adg
CC=golang-dev
https://golang.org/cl/7057049

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

https://github.com/golang/go/commit/8cf45909b59dbc9edf856b129c6b84603438973b

元コミット内容

commit 8cf45909b59dbc9edf856b129c6b84603438973b
Author: Matthew Dempsky <mdempsky@google.com>
Date:   Sun Jan 6 22:43:32 2013 -0500

    bytes: Change Compare example to be consistent with sort.Search's.
    
    R=rsc, adg
    CC=golang-dev
    https://golang.org/cl/7057049
---
 src/pkg/bytes/example_test.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pkg/bytes/example_test.go b/src/pkg/bytes/example_test.go
index 5f7e18c9f6..dc66b6a40f 100644
--- a/src/pkg/bytes/example_test.go
+++ b/src/pkg/bytes/example_test.go
@@ -59,10 +59,10 @@ func ExampleCompare_search() {
 	var needle []byte
 	var haystack [][]byte // Assume sorted
 	i := sort.Search(len(haystack), func(i int) bool {
-\t\t// Return needle <= haystack[i].
-\t\treturn bytes.Compare(needle, haystack[i]) <= 0
+\t\t// Return haystack[i] >= needle.
+\t\treturn bytes.Compare(haystack[i], needle) >= 0
 \t})\
-\tif i < len(haystack) && bytes.Equal(needle, haystack[i]) {\
+\tif i < len(haystack) && bytes.Equal(haystack[i], needle) {\
 \t\t// Found it!\
 \t}\
 }\

変更の背景

このコミットの背景には、Go言語の標準ライブラリにおけるコード例の整合性と、sort.Search関数の意図する利用パターンへの準拠があります。

sort.Search関数は、ソートされたデータ構造内で特定の要素を効率的に検索するための強力なツールです。この関数は、与えられた述語(predicate)関数がtrueを返す最初のインデックスを返します。この述語関数は、通常、検索対象の要素が現在のインデックスの要素以上であるかどうかを判断するために使用されます。

元のコード例では、bytes.Compare(needle, haystack[i]) <= 0という条件を使用していました。これは「needlehaystack[i]以下である場合にtrueを返す」という意味になります。しかし、sort.Searchの一般的な慣習やドキュメントでは、述語関数は「haystack[i]needle以上である場合にtrueを返す」という形式で記述されることが推奨されます。つまり、haystack[i] >= needleという論理に対応するべきです。

この変更は、bytes.Compareの引数の順序を入れ替えることで、この慣習に合わせることを目的としています。bytes.Compare(haystack[i], needle) >= 0は、「haystack[i]needle以上である場合にtrueを返す」という、より直感的でsort.Searchの意図に合致した表現になります。

また、bytes.Equalの引数の順序も同様に変更されています。これは、検索で見つかった要素が実際にneedleと等しいかどうかの最終確認を行う部分であり、ここでも一貫性を保つことが重要です。

この修正は、機能的なバグを修正するものではなく、主にコードの可読性、慣習への準拠、および将来的な誤解を防ぐための改善です。Go言語の標準ライブラリの例は、ユーザーがライブラリを正しく効果的に使用するためのガイドとなるため、このような細かな一貫性の修正も重要視されます。

前提知識の解説

1. bytesパッケージとbytes.Compare関数

Go言語のbytesパッケージは、バイトスライス([]byte)を操作するためのユーティリティ関数を提供します。 bytes.Compare関数は、2つのバイトスライスを辞書順に比較します。そのシグネチャは以下の通りです。

func Compare(a, b []byte) int

戻り値の意味は以下の通りです。

  • a < b の場合、負の整数(通常は-1)
  • a == b の場合、0
  • a > b の場合、正の整数(通常は+1)

この関数は、文字列の比較と同様に、バイトスライスのソートや検索に利用されます。

2. sortパッケージとsort.Search関数

Go言語のsortパッケージは、ソートされたスライスを操作するための関数を提供します。 sort.Search関数は、ソートされたデータ構造内で特定の要素を検索するためのバイナリサーチ(二分探索)アルゴリズムを実装しています。そのシグネチャは以下の通りです。

func Search(n int, f func(i int) bool) int
  • n: 検索対象のスライスの長さ。
  • f: 述語(predicate)関数。この関数は、インデックスiを受け取り、trueまたはfalseを返します。sort.Searchは、f(i)trueを返す最小のインデックスiを返します。もしそのようなインデックスが存在しない場合(つまり、すべての要素に対してffalseを返す場合)、nを返します。

sort.Searchの重要な特性は、述語関数fが以下の条件を満たす必要があることです。

  • f(i)は、iが小さい間はfalseを返し、iがある点を超えるとtrueを返し続ける(単調性)。
  • 通常、f(i)は「data[i]が検索対象の値以上である」という条件を表現します。

3. bytes.Equal関数

bytes.Equal関数は、2つのバイトスライスが等しいかどうかを比較します。

func Equal(a, b []byte) bool
  • abが同じ長さで、かつすべての要素が等しい場合にtrueを返します。それ以外の場合はfalseを返します。

4. 検索における「Needle」と「Haystack」

検索アルゴリズムの文脈で、「Needle(針)」は検索したい特定の要素を指し、「Haystack(干し草の山)」は検索対象となるデータコレクション(この場合はバイトスライスのスライス)を指します。このコミットのコード例でも、needlehaystackという変数名が使われています。

技術的詳細

このコミットの核心は、sort.Searchの述語関数の慣用的な記述方法と、bytes.Compareの戻り値の解釈にあります。

sort.Search(n int, f func(i int) bool) intは、f(i)trueを返す最小のiを探索します。このf(i)は、通常、ソートされた配列dataにおいて「data[i]が目的の値x以上である」という条件を表します。つまり、data[i] >= xです。

元のコードでは、述語関数は以下のようになっていました。

func(i int) bool {
    // Return needle <= haystack[i].
    return bytes.Compare(needle, haystack[i]) <= 0
}

ここで、bytes.Compare(a, b)は、a < bなら負、a == bなら0、a > bなら正を返します。 したがって、bytes.Compare(needle, haystack[i]) <= 0は、以下のいずれかの条件が満たされる場合にtrueを返します。

  1. needle < haystack[i] (Compareが負を返す)
  2. needle == haystack[i] (Compareが0を返す)

これは、論理的には「needlehaystack[i]以下である」ということを意味します。

一方、修正後のコードでは、述語関数は以下のようになりました。

func(i int) bool {
    // Return haystack[i] >= needle.
    return bytes.Compare(haystack[i], needle) >= 0
}

ここで、bytes.Compare(haystack[i], needle) >= 0は、以下のいずれかの条件が満たされる場合にtrueを返します。

  1. haystack[i] > needle (Compareが正を返す)
  2. haystack[i] == needle (Compareが0を返す)

これは、論理的には「haystack[i]needle以上である」ということを意味します。

この変更は、sort.Searchのドキュメントや他の例で一般的に見られる「data[i] >= x」という形式に完全に合致します。この形式は、バイナリサーチの性質上、検索対象の値xが配列内に存在しない場合でも、xを挿入すべき位置(またはx以上の最初の要素の位置)を正確に特定するために重要です。

例えば、haystack[["a"], ["c"]]で、needle"b"の場合を考えます。

  • 元の述語: bytes.Compare("b", haystack[i]) <= 0

    • i=0: bytes.Compare("b", "a") <= 0 -> false (b > a)
    • i=1: bytes.Compare("b", "c") <= 0 -> true (b < c) sort.Searchi=1を返します。これは正しい結果です。
  • 修正後の述語: bytes.Compare(haystack[i], "b") >= 0

    • i=0: bytes.Compare("a", "b") >= 0 -> false (a < b)
    • i=1: bytes.Compare("c", "b") >= 0 -> true (c > b) sort.Searchi=1を返します。これも正しい結果です。

どちらの論理も最終的な検索結果には影響を与えませんが、後者の形式がsort.Searchの設計思想とより密接に連携しており、コードの意図をより明確に伝えます。これは、Go言語のコードベース全体で一貫性を保つための重要な変更です。

また、bytes.Equal(needle, haystack[i])からbytes.Equal(haystack[i], needle)への変更も、同様に引数の順序の一貫性を保つためのものです。bytes.Equalは引数の順序に依存しないため、機能的な違いはありませんが、Compare関数での変更と合わせて、コード全体の読みやすさと一貫性が向上します。

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

変更はsrc/pkg/bytes/example_test.goファイル内のExampleCompare_search関数に集中しています。

--- a/src/pkg/bytes/example_test.go
+++ b/src/pkg/bytes/example_test.go
@@ -59,10 +59,10 @@ func ExampleCompare_search() {
 	var needle []byte
 	var haystack [][]byte // Assume sorted
 	i := sort.Search(len(haystack), func(i int) bool {
-\t\t// Return needle <= haystack[i].
-\t\treturn bytes.Compare(needle, haystack[i]) <= 0
+\t\t// Return haystack[i] >= needle.
+\t\treturn bytes.Compare(haystack[i], needle) >= 0
 \t})\
-\tif i < len(haystack) && bytes.Equal(needle, haystack[i]) {\
+\tif i < len(haystack) && bytes.Equal(haystack[i], needle) {\
 \t\t// Found it!\
 \t}\
 }\

具体的には、以下の2行が変更されました。

  1. return bytes.Compare(needle, haystack[i]) <= 0return bytes.Compare(haystack[i], needle) >= 0 に変更。

  2. if i < len(haystack) && bytes.Equal(needle, haystack[i]) {if i < len(haystack) && bytes.Equal(haystack[i], needle) { に変更。

コメントも変更され、述語関数の意図が「haystack[i] >= needle」であることが明確に示されています。

コアとなるコードの解説

変更前

i := sort.Search(len(haystack), func(i int) bool {
    // Return needle <= haystack[i].
    return bytes.Compare(needle, haystack[i]) <= 0
})
if i < len(haystack) && bytes.Equal(needle, haystack[i]) {
    // Found it!
}

このコードでは、sort.Searchの述語関数内でbytes.Compare(needle, haystack[i]) <= 0という条件を使用しています。これは「needlehaystack[i]以下である」という論理を表します。sort.Searchは、この条件がtrueになる最初のインデックスiを返します。

その後のif文では、ihaystackの範囲内であり、かつneedlehaystack[i]が完全に等しい場合に要素が見つかったと判断しています。

変更後

i := sort.Search(len(haystack), func(i int) bool {
    // Return haystack[i] >= needle.
    return bytes.Compare(haystack[i], needle) >= 0
})
if i < len(haystack) && bytes.Equal(haystack[i], needle) {
    // Found it!
}

変更後のコードでは、述語関数がbytes.Compare(haystack[i], needle) >= 0となりました。これは「haystack[i]needle以上である」という論理を表します。この形式は、sort.Searchのドキュメントで推奨される述語の形式と一致しており、より慣用的なGoのコードスタイルに準拠しています。

bytes.Equalの引数の順序もbytes.Equal(haystack[i], needle)に変更されました。これは機能的には同じですが、Compare関数での引数順序の変更と合わせて、コード全体の一貫性を高めています。

この変更は、コードの動作を変えるものではなく、主に可読性とGo言語の慣習への準拠を目的としています。これにより、他の開発者がこのコード例を読んだ際に、sort.Searchの一般的な使用パターンをより正確に理解できるようになります。

関連リンク

参考にした情報源リンク

このコミットは、Go言語の標準ライブラリbytesパッケージ内のExampleCompare_search関数の例を修正するものです。具体的には、sort.Search関数を使用する際のbytes.Compareの利用方法が、sort.Searchの一般的な慣習と一貫性を持つように変更されています。

コミット

bytes: Change Compare example to be consistent with sort.Search's.

R=rsc, adg
CC=golang-dev
https://golang.org/cl/7057049

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

https://github.com/golang/go/commit/8cf45909b59dbc9edf856b129c6b84603438973b

元コミット内容

commit 8cf45909b59dbc9edf856b129c6b84603438973b
Author: Matthew Dempsky <mdempsky@google.com>
Date:   Sun Jan 6 22:43:32 2013 -0500

    bytes: Change Compare example to be consistent with sort.Search's.
    
    R=rsc, adg
    CC=golang-dev
    https://golang.org/cl/7057049
---
 src/pkg/bytes/example_test.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/pkg/bytes/example_test.go b/src/pkg/bytes/example_test.go
index 5f7e18c9f6..dc66b6a40f 100644
--- a/src/pkg/bytes/example_test.go
+++ b/src/pkg/bytes/example_test.go
@@ -59,10 +59,10 @@ func ExampleCompare_search() {
 	var needle []byte
 	var haystack [][]byte // Assume sorted
 	i := sort.Search(len(haystack), func(i int) bool {
-\t\t// Return needle <= haystack[i].
-\t\treturn bytes.Compare(needle, haystack[i]) <= 0
+\t\t// Return haystack[i] >= needle.
+\t\treturn bytes.Compare(haystack[i], needle) >= 0
 \t})\
-\tif i < len(haystack) && bytes.Equal(needle, haystack[i]) {\
+\tif i < len(haystack) && bytes.Equal(haystack[i], needle) {\
 \t\t// Found it!\
 \t}\
 }\

変更の背景

このコミットの背景には、Go言語の標準ライブラリにおけるコード例の整合性と、sort.Search関数の意図する利用パターンへの準拠があります。

sort.Search関数は、ソートされたデータ構造内で特定の要素を効率的に検索するための強力なツールです。この関数は、与えられた述語(predicate)関数がtrueを返す最初のインデックスを返します。この述語関数は、通常、検索対象の要素が現在のインデックスの要素以上であるかどうかを判断するために使用されます。

元のコード例では、bytes.Compare(needle, haystack[i]) <= 0という条件を使用していました。これは「needlehaystack[i]以下である場合にtrueを返す」という意味になります。しかし、sort.Searchの一般的な慣習やドキュメントでは、述語関数は「haystack[i]needle以上である場合にtrueを返す」という形式で記述されることが推奨されます。つまり、haystack[i] >= needleという論理に対応するべきです。

この変更は、bytes.Compareの引数の順序を入れ替えることで、この慣習に合わせることを目的としています。bytes.Compare(haystack[i], needle) >= 0は、「haystack[i]needle以上である場合にtrueを返す」という、より直感的でsort.Searchの意図に合致した表現になります。

また、bytes.Equalの引数の順序も同様に変更されています。これは、検索で見つかった要素が実際にneedleと等しいかどうかの最終確認を行う部分であり、ここでも一貫性を保つことが重要です。

この修正は、機能的なバグを修正するものではなく、主にコードの可読性、慣習への準拠、および将来的な誤解を防ぐための改善です。Go言語の標準ライブラリの例は、ユーザーがライブラリを正しく効果的に使用するためのガイドとなるため、このような細かな一貫性の修正も重要視されます。

前提知識の解説

1. bytesパッケージとbytes.Compare関数

Go言語のbytesパッケージは、バイトスライス([]byte)を操作するためのユーティリティ関数を提供します。 bytes.Compare関数は、2つのバイトスライスを辞書順に比較します。そのシグネチャは以下の通りです。

func Compare(a, b []byte) int

戻り値の意味は以下の通りです。

  • a < b の場合、負の整数(通常は-1)
  • a == b の場合、0
  • a > b の場合、正の整数(通常は+1)

この関数は、文字列の比較と同様に、バイトスライスのソートや検索に利用されます。

2. sortパッケージとsort.Search関数

Go言語のsortパッケージは、ソートされたスライスを操作するための関数を提供します。 sort.Search関数は、ソートされたデータ構造内で特定の要素を検索するためのバイナリサーチ(二分探索)アルゴリズムを実装しています。そのシグネチャは以下の通りです。

func Search(n int, f func(i int) bool) int
  • n: 検索対象のスライスの長さ。
  • f: 述語(predicate)関数。この関数は、インデックスiを受け取り、trueまたはfalseを返します。sort.Searchは、f(i)trueを返す最小のインデックスiを返します。もしそのようなインデックスが存在しない場合(つまり、すべての要素に対してffalseを返す場合)、nを返します。

sort.Searchの重要な特性は、述語関数fが以下の条件を満たす必要があることです。

  • f(i)は、iが小さい間はfalseを返し、iがある点を超えるとtrueを返し続ける(単調性)。
  • 通常、f(i)は「data[i]が検索対象の値以上である」という条件を表現します。

3. bytes.Equal関数

bytes.Equal関数は、2つのバイトスライスが等しいかどうかを比較します。

func Equal(a, b []byte) bool
  • abが同じ長さで、かつすべての要素が等しい場合にtrueを返します。それ以外の場合はfalseを返します。

4. 検索における「Needle」と「Haystack」

検索アルゴリズムの文脈で、「Needle(針)」は検索したい特定の要素を指し、「Haystack(干し草の山)」は検索対象となるデータコレクション(この場合はバイトスライスのスライス)を指します。このコミットのコード例でも、needlehaystackという変数名が使われています。

技術的詳細

このコミットの核心は、sort.Searchの述語関数の慣用的な記述方法と、bytes.Compareの戻り値の解釈にあります。

sort.Search(n int, f func(i int) bool) intは、f(i)trueを返す最小のiを探索します。このf(i)は、通常、ソートされた配列dataにおいて「data[i]が目的の値x以上である」という条件を表します。つまり、data[i] >= xです。

元のコードでは、述語関数は以下のようになっていました。

func(i int) bool {
    // Return needle <= haystack[i].
    return bytes.Compare(needle, haystack[i]) <= 0
}

ここで、bytes.Compare(a, b)は、a < bなら負、a == bなら0、a > bなら正を返します。 したがって、bytes.Compare(needle, haystack[i]) <= 0は、以下のいずれかの条件が満たされる場合にtrueを返します。

  1. needle < haystack[i] (Compareが負を返す)
  2. needle == haystack[i] (Compareが0を返す)

これは、論理的には「needlehaystack[i]以下である」ということを意味します。

一方、修正後のコードでは、述語関数は以下のようになりました。

func(i int) bool {
    // Return haystack[i] >= needle.
    return bytes.Compare(haystack[i], needle) >= 0
}

ここで、bytes.Compare(haystack[i], needle) >= 0は、以下のいずれかの条件が満たされる場合にtrueを返します。

  1. haystack[i] > needle (Compareが正を返す)
  2. haystack[i] == needle (Compareが0を返す)

これは、論理的には「haystack[i]needle以上である」ということを意味します。

この変更は、sort.Searchのドキュメントや他の例で一般的に見られる「data[i] >= x」という形式に完全に合致します。この形式は、バイナリサーチの性質上、検索対象の値xが配列内に存在しない場合でも、xを挿入すべき位置(またはx以上の最初の要素の位置)を正確に特定するために重要です。

例えば、haystack[["a"], ["c"]]で、needle"b"の場合を考えます。

  • 元の述語: bytes.Compare("b", haystack[i]) <= 0

    • i=0: bytes.Compare("b", "a") <= 0 -> false (b > a)
    • i=1: bytes.Compare("b", "c") <= 0 -> true (b < c) sort.Searchi=1を返します。これは正しい結果です。
  • 修正後の述語: bytes.Compare(haystack[i], "b") >= 0

    • i=0: bytes.Compare("a", "b") >= 0 -> false (a < b)
    • i=1: bytes.Compare("c", "b") >= 0 -> true (c > b) sort.Searchi=1を返します。これも正しい結果です。

どちらの論理も最終的な検索結果には影響を与えませんが、後者の形式がsort.Searchの設計思想とより密接に連携しており、コードの意図をより明確に伝えます。これは、Go言語のコードベース全体で一貫性を保つための重要な変更です。

また、bytes.Equal(needle, haystack[i])からbytes.Equal(haystack[i], needle)への変更も、同様に引数の順序の一貫性を保つためのものです。bytes.Equalは引数の順序に依存しないため、機能的な違いはありませんが、Compare関数での変更と合わせて、コード全体の読みやすさと一貫性が向上します。

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

変更はsrc/pkg/bytes/example_test.goファイル内のExampleCompare_search関数に集中しています。

--- a/src/pkg/bytes/example_test.go
+++ b/src/pkg/bytes/example_test.go
@@ -59,10 +59,10 @@ func ExampleCompare_search() {
 	var needle []byte
 	var haystack [][]byte // Assume sorted
 	i := sort.Search(len(haystack), func(i int) bool {
-\t\t// Return needle <= haystack[i].
-\t\treturn bytes.Compare(needle, haystack[i]) <= 0
+\t\t// Return haystack[i] >= needle.
+\t\treturn bytes.Compare(haystack[i], needle) >= 0
 \t})\
-\tif i < len(haystack) && bytes.Equal(needle, haystack[i]) {\
+\tif i < len(haystack) && bytes.Equal(haystack[i], needle) {\
 \t\t// Found it!\
 \t}\
 }\

具体的には、以下の2行が変更されました。

  1. return bytes.Compare(needle, haystack[i]) <= 0return bytes.Compare(haystack[i], needle) >= 0 に変更。

  2. if i < len(haystack) && bytes.Equal(needle, haystack[i]) {if i < len(haystack) && bytes.Equal(haystack[i], needle) { に変更。

コメントも変更され、述語関数の意図が「haystack[i] >= needle」であることが明確に示されています。

コアとなるコードの解説

変更前

i := sort.Search(len(haystack), func(i int) bool {
    // Return needle <= haystack[i].
    return bytes.Compare(needle, haystack[i]) <= 0
})
if i < len(haystack) && bytes.Equal(needle, haystack[i]) {
    // Found it!
}

このコードでは、sort.Searchの述語関数内でbytes.Compare(needle, haystack[i]) <= 0という条件を使用しています。これは「needlehaystack[i]以下である」という論理を表します。sort.Searchは、この条件がtrueになる最初のインデックスiを返します。

その後のif文では、ihaystackの範囲内であり、かつneedlehaystack[i]が完全に等しい場合に要素が見つかったと判断しています。

変更後

i := sort.Search(len(haystack), func(i int) bool {
    // Return haystack[i] >= needle.
    return bytes.Compare(haystack[i], needle) >= 0
})
if i < len(haystack) && bytes.Equal(haystack[i], needle) {
    // Found it!
}

変更後のコードでは、述語関数がbytes.Compare(haystack[i], needle) >= 0となりました。これは「haystack[i]needle以上である」という論理を表します。この形式は、sort.Searchのドキュメントで推奨される述語の形式と一致しており、より慣用的なGoのコードスタイルに準拠しています。

bytes.Equalの引数の順序もbytes.Equal(haystack[i], needle)に変更されました。これは機能的には同じですが、Compare関数での引数順序の変更と合わせて、コード全体の一貫性を高めています。

この変更は、コードの動作を変えるものではなく、主に可読性とGo言語の慣習への準拠を目的としています。これにより、他の開発者がこのコード例を読んだ際に、sort.Searchの一般的な使用パターンをより正確に理解できるようになります。

関連リンク

参考にした情報源リンク