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

[インデックス 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]] のように文字列スライスを例示していましたが、FindReaderIndexio.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]]. は、FindReaderIndexio.RuneReader を引数にとるにもかかわらず、あたかも文字列 s から直接スライスできるかのように誤解を招く可能性がありました。また、io.RuneReader がルーン単位で読み取るため、インデックスがルーンオフセットであると誤解される可能性もありました。

このコミットでは、この曖昧さを解消するためにドキュメントが修正されました。新しい記述 The match text was found in the input stream at byte offset loc[0] through loc[1]-1. は、以下の点を明確にしています。

  1. マッチしたテキストが「入力ストリーム」内で見つかったこと。これにより、io.RuneReader からの入力であることを示唆しています。
  2. インデックスが「バイトオフセット」であること。これにより、ルーンオフセットとの混同を防ぎます。
  3. 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 この行は、FindReaderIndexio.RuneReader から読み取った内容に対してマッチングを行うにもかかわらず、結果をあたかも文字列 s からスライスできるかのように説明していました。これは、FindStringIndex のような文字列を直接扱う関数との混同を招く可能性がありました。

変更後のコメント: // the RuneReader. The match text was found in the input stream at // byte offset loc[0] through loc[1]-1. この2行は、以下の重要な点を明確にしています。

  1. 入力源の明確化: 「the input stream」という表現により、io.RuneReader からのストリームデータに対してマッチングが行われたことを示唆しています。
  2. インデックスの単位の明確化: 「byte offset」という言葉を明示的に追加することで、loc[0]loc[1] がバイト単位のオフセットであることを明確にしています。これにより、ルーンオフセットとの混同を防ぎます。
  3. 範囲の正確な記述: 「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は見つからなかったが、文脈理解の助けとなった)