[インデックス 13536] ファイルの概要
このコミットは、Go言語の標準ライブラリである regexp
パッケージ内の regexp.go
ファイルに対するドキュメントの修正です。具体的には、FindReaderIndex
関数のコメントにおける説明の曖昧さを解消し、より正確な情報を提供する変更が行われています。
コミット
commit 4783ad82dac77de7bcb49d6addefdf758412bfe5
Author: Rob Pike <r@golang.org>
Date: Mon Jul 30 12:46:50 2012 -0700
regexp: fix glitch in doc for FindReaderIndex
Fixes #3878.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6457054
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4783ad82dac77de7bcb49d6addefdf758412bfe5
元コミット内容
regexp: fix glitch in doc for FindReaderIndex
Fixes #3878.
変更の背景
このコミットの背景には、Go言語の regexp
パッケージにおける FindReaderIndex
関数のドキュメントが、その戻り値の意味について誤解を招く可能性があったという問題があります。FindReaderIndex
は、io.RuneReader
から読み取ったテキストに対して正規表現のマッチングを行い、マッチした部分の開始と終了のインデックスを返します。
元のドキュメントでは、s[loc[0]:loc[1]]
のように文字列スライスを例示していましたが、FindReaderIndex
は io.RuneReader
を引数にとるため、直接文字列 s
からスライスするわけではありません。また、io.RuneReader
はバイトストリームではなくルーン(Unicodeコードポイント)のストリームを扱うため、インデックスがバイトオフセットを指すのか、ルーンオフセットを指すのかが不明瞭でした。
この曖昧さが、ユーザーが関数を正しく理解し、利用する上での「glitch」(小さな問題、不具合)として認識され、Fixes #3878
として報告された問題に対応するためにドキュメントの修正が必要となりました。
前提知識の解説
正規表現 (Regular Expression)
正規表現は、文字列のパターンを記述するための強力なツールです。特定の文字の並び、繰り返し、選択などを簡潔に表現でき、テキストの検索、置換、検証などに広く用いられます。Go言語の regexp
パッケージは、この正規表現の機能を提供します。
Go言語の regexp
パッケージ
Go言語の regexp
パッケージは、RE2構文(Googleが開発した高速な正規表現エンジン)に基づいた正規表現の実装を提供します。このパッケージは、文字列やバイトスライス、io.Reader
からの入力に対して正規表現のマッチングを行うための様々な関数やメソッドを提供します。
io.RuneReader
インターフェース
io.RuneReader
はGo言語の io
パッケージで定義されているインターフェースです。これは、ReadRune() (r rune, size int, err error)
メソッドを持つ型が実装するもので、入力ストリームから1つのUnicodeルーン(rune
型)とそのルーンをエンコードするために読み取られたバイト数(size
)を返します。これにより、マルチバイト文字エンコーディング(例: UTF-8)を意識することなく、ルーン単位でテキストを処理することが可能になります。
FindReaderIndex
関数
regexp.Regexp
型のメソッドである FindReaderIndex
は、io.RuneReader
から読み取られるテキストに対して正規表現のマッチングを行い、最初に見つかったマッチの開始と終了のインデックスを []int
型のスライスとして返します。このインデックスは、入力ストリームの先頭からのバイトオフセットを示します。
バイトオフセットとルーンオフセット
テキストデータを扱う際、特にUnicodeのような可変長エンコーディング(例: UTF-8)を使用する場合、文字の位置を示す方法として「バイトオフセット」と「ルーンオフセット」の2種類があります。
- バイトオフセット: テキストの先頭から数えたバイト単位での位置。UTF-8では1つのルーンが1バイトから4バイトを占めるため、ルーンの数とバイト数は一致しません。
- ルーンオフセット: テキストの先頭から数えたルーン(文字)単位での位置。
FindReaderIndex
が返すインデックスはバイトオフセットであり、これがドキュメントで明確にされる必要がありました。
技術的詳細
regexp.Regexp
型の FindReaderIndex
メソッドは、io.RuneReader
を介して提供される入力ストリームに対して正規表現のマッチングを実行します。このメソッドは、マッチが見つかった場合、loc []int
という形式の2要素スライスを返します。loc[0]
はマッチの開始バイトオフセットを、loc[1]
はマッチの終了バイトオフセット(排他的)を示します。
元のドキュメントの記述 The match itself is at s[loc[0]:loc[1]].
は、FindReaderIndex
が io.RuneReader
を引数にとるにもかかわらず、あたかも文字列 s
から直接スライスできるかのように誤解を招く可能性がありました。また、io.RuneReader
がルーン単位で読み取るため、インデックスがルーンオフセットであると誤解される可能性もありました。
このコミットでは、この曖昧さを解消するためにドキュメントが修正されました。新しい記述 The match text was found in the input stream at byte offset loc[0] through loc[1]-1.
は、以下の点を明確にしています。
- マッチしたテキストが「入力ストリーム」内で見つかったこと。これにより、
io.RuneReader
からの入力であることを示唆しています。 - インデックスが「バイトオフセット」であること。これにより、ルーンオフセットとの混同を防ぎます。
loc[0]
が開始バイトオフセット、loc[1]-1
が終了バイトオフセット(包含的)であることを明確にしています。これは、Goのスライス表記[start:end]
がstart
からend-1
までを意味することと整合しています。
この修正は、関数の動作自体を変更するものではなく、そのドキュメントをより正確で理解しやすいものにすることを目的としています。
コアとなるコードの変更箇所
変更は src/pkg/regexp/regexp.go
ファイルの FindReaderIndex
関数のドキュメントコメントにあります。
--- a/src/pkg/regexp/regexp.go
+++ b/src/pkg/regexp/regexp.go
@@ -686,8 +686,9 @@ func (re *Regexp) FindStringIndex(s string) (loc []int) {
// FindReaderIndex returns a two-element slice of integers defining the
// location of the leftmost match of the regular expression in text read from
-// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
-// value of nil indicates no match.
+// the RuneReader. The match text was found in the input stream at
+// byte offset loc[0] through loc[1]-1.
+// A return value of nil indicates no match.
func (re *Regexp) FindReaderIndex(r io.RuneReader) (loc []int) {
a := re.doExecute(r, nil, "", 0, 2)
if a == nil {
具体的には、以下の2行が変更されました。
- the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
+ the RuneReader. The match text was found in the input stream at
+ byte offset loc[0] through loc[1]-1.
コアとなるコードの解説
このコミットにおける「コアとなるコードの変更箇所」は、実際にはコードの動作を変更するものではなく、そのコードの振る舞いを説明するドキュメントコメントの修正です。
変更前のコメント:
// the RuneReader. The match itself is at s[loc[0]:loc[1]]. A return
この行は、FindReaderIndex
が io.RuneReader
から読み取った内容に対してマッチングを行うにもかかわらず、結果をあたかも文字列 s
からスライスできるかのように説明していました。これは、FindStringIndex
のような文字列を直接扱う関数との混同を招く可能性がありました。
変更後のコメント:
// the RuneReader. The match text was found in the input stream at
// byte offset loc[0] through loc[1]-1.
この2行は、以下の重要な点を明確にしています。
- 入力源の明確化: 「
the input stream
」という表現により、io.RuneReader
からのストリームデータに対してマッチングが行われたことを示唆しています。 - インデックスの単位の明確化: 「
byte offset
」という言葉を明示的に追加することで、loc[0]
とloc[1]
がバイト単位のオフセットであることを明確にしています。これにより、ルーンオフセットとの混同を防ぎます。 - 範囲の正確な記述: 「
loc[0] through loc[1]-1
」という記述は、Go言語のスライス表記[start:end]
がstart
からend-1
までの範囲(end
は排他的)を意味することと完全に一致しており、マッチしたテキストの正確なバイト範囲を示しています。
この修正により、FindReaderIndex
のユーザーは、戻り値の loc
スライスが示すインデックスが、io.RuneReader
から読み取られたバイトストリームにおけるバイトオフセットであり、その範囲が loc[0]
から loc[1]-1
までであることを正確に理解できるようになりました。これは、関数の誤用を防ぎ、より堅牢なコードを書く上で非常に重要です。
関連リンク
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/13536.txt
- GitHubコミットページ: https://github.com/golang/go/commit/4783ad82dac77de7bcb49d6addefdf758412bfe5
- Go言語の公式ドキュメント
- 正規表現に関する一般的な知識
io.RuneReader
インターフェースに関する一般的な知識Fixes #3878
についてのWeb検索(直接的なGo言語のIssueは見つからなかったが、文脈理解の助けとなった)