[インデックス 14580] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html
)におけるメソッド式のレシーバ型に関する記述を更新するものです。具体的には、メソッド式におけるレシーバ型が括弧で囲むことができるようになったことを反映し、その文法定義(EBNF)と使用例が修正されています。
コミット
commit e06d90136f18fbb1ffa46537d01eb3552f45b0bc
Author: Robert Griesemer <gri@golang.org>
Date: Thu Dec 6 09:31:42 2012 -0800
spec: receiver types in method expressions can be parenthesized
Fixes #4457.
R=rsc, iant, r, ken
CC=golang-dev
https://golang.org/cl/6862046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/e06d90136f18fbb1ffa46537d01eb3552f45b0bc
元コミット内容
このコミットの目的は、Go言語の仕様において、メソッド式(Method Expression)のレシーバ型(Receiver Type)を括弧で囲むことを許可するように変更し、その変更を仕様書に反映することです。これにより、より柔軟な記述が可能になります。
変更の背景
Go言語では、メソッドは特定の型(レシーバ型)に関連付けられた関数です。メソッド式は、レシーバ型からメソッド関数を取得するための構文を提供します。例えば、T.Mv
のように記述することで、型 T
のメソッド Mv
を関数として取得できます。
このコミット以前は、レシーバ型は TypeName
またはポインタ型 (*TypeName)
の形式でしか記述できませんでした。しかし、Go言語の他の部分では、型を括弧で囲むことが許容される場合があります。この不整合を解消し、より一貫性のある構文を提供するために、メソッド式のレシーバ型も括弧で囲むことができるように仕様が拡張されました。
コミットメッセージにある Fixes #4457
は、この変更が特定の課題(Issue 4457)を解決するものであることを示唆しています。この課題は、おそらくレシーバ型に括弧を使用できないことによる構文上の制限や、それによって生じる不便さに関するものだったと考えられます。
前提知識の解説
Go言語のメソッドとレシーバ
Go言語において、メソッドは特定の型(レシーバ型)に関連付けられた関数です。メソッドは、レシーバ引数を持つ通常の関数として定義されます。
type MyType int
func (m MyType) MyMethod() {
// ...
}
func (m *MyType) PointerMethod() {
// ...
}
上記の例では、MyMethod
は MyType
の値レシーバメソッドであり、PointerMethod
は *MyType
のポインタレシーバメソッドです。
メソッド式 (Method Expressions)
メソッド式は、レシーバ型からメソッド関数を取得するための構文です。これは、特定のインスタンスにバインドされていない「関数テンプレート」のようなものです。メソッド式によって取得された関数は、最初の引数としてレシーバを受け取ります。
例:
T.Mv
は、型 T
のメソッド Mv
を表すメソッド式です。この式の結果は、func(T, args...)
のようなシグネチャを持つ関数となります。
type T int
func (t T) Mv(a int) int {
return int(t) + a
}
func main() {
var t T = 10
// 通常のメソッド呼び出し
t.Mv(7) // => 17
// メソッド式
f := T.Mv // f は func(T, int) int 型の関数
f(t, 7) // => 17
}
EBNF (Extended Backus-Naur Form)
EBNFは、プログラミング言語の構文を記述するためのメタ言語です。Go言語の仕様書でも、構文規則を定義するためにEBNFが使用されています。
|
(パイプ): 論理OR。選択肢を示します。()
(括弧): グループ化。*
(アスタリスク): 0回以上の繰り返し。
技術的詳細
このコミットの主要な変更点は、Go言語の仕様書(doc/go_spec.html
)における ReceiverType
のEBNF定義の変更です。
変更前:
ReceiverType = TypeName | "(" "*" TypeName ")" .
これは、ReceiverType
が TypeName
(例: T
)または (*TypeName)
(例: (*T)
)のいずれかであることを意味していました。
変更後:
ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
この変更により、ReceiverType
の定義に | "(" ReceiverType ")"
が追加されました。これは、ReceiverType
自体をさらに括弧で囲むことができるようになったことを意味します。つまり、T
だけでなく、(T)
や ((T))
のように、任意の深さで括弧をネストしてレシーバ型を記述することが可能になります。
この変更は、メソッド式の構文解析において、レシーバ型がより柔軟に表現されることを可能にします。例えば、T.Mv
と同様に (T).Mv
も有効なメソッド式として認識されるようになります。
また、仕様書の例も更新され、この新しい構文がどのように使用されるかを示しています。
変更前の例の記述:
these three invocations are equivalent:
変更後の例の記述:
these five invocations are equivalent:
追加された例は以下の通りです。
(T).Mv(t, t)
: 型T
を括弧で囲んだ形式でメソッド式を呼び出す例。f2 := (T).Mv; f2(t, 7)
: 括弧で囲んだ型からメソッド式を取得し、それを変数に代入して呼び出す例。
これらの例は、レシーバ型を括弧で囲むことが、直接のメソッド呼び出しと、メソッド式を変数に代入してからの呼び出しの両方で有効であることを明確に示しています。
コアとなるコードの変更箇所
変更は doc/go_spec.html
ファイルに集中しており、Go言語の仕様書の一部を修正しています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -3316,7 +3316,7 @@ argument that is the receiver of the method.
<pre class="ebnf">
MethodExpr = ReceiverType "." MethodName .
-ReceiverType = TypeName | "(" "*" TypeName ")" .
+ReceiverType = TypeName | "(" "*" TypeName ")" | "(" ReceiverType ")" .
</pre>
<p>
@@ -3353,13 +3353,15 @@ func(tv T, a int) int
<p>
That function may be called normally with an explicit receiver, so
-these three invocations are equivalent:
+these five invocations are equivalent:
</p>
<pre>
t.Mv(7)
T.Mv(t, 7)
-f := T.Mv; f(t, 7)
+(T).Mv(t, t)
+f1 := T.Mv; f1(t, 7)
+f2 := (T).Mv; f2(t, 7)
</pre>
<p>
コアとなるコードの解説
-
EBNF定義の変更:
ReceiverType
の定義がTypeName | "(" "*" TypeName ")" | "(" ReceiverType ")"
に変更されました。これにより、ReceiverType
が再帰的に括弧で囲むことが可能になり、(T)
や(*T)
のような形式だけでなく、((T))
や((*T))
のような形式も文法的に正しくなりました。これは、Goコンパイラがこれらの新しい形式のレシーバ型を正しく解析できるようになることを意味します。 -
例の追加: 既存のメソッド呼び出しの等価性の例に、
(T).Mv(t, t)
とf2 := (T).Mv; f2(t, 7)
の2つの新しいパターンが追加されました。これらの例は、括弧で囲まれたレシーバ型がどのようにメソッド式で使用され、それが従来の形式と同等に機能するかを具体的に示しています。これにより、仕様の変更が開発者にとってより理解しやすくなります。
この変更は、Go言語の構文の一貫性を高め、開発者がより自然な方法でメソッド式を記述できるようにすることを目的としています。
関連リンク
- Go言語の仕様書: https://go.dev/ref/spec (このコミットが修正したドキュメントの最新版)
- Go言語のメソッド式に関するセクション (最新の仕様書): https://go.dev/ref/spec#Method_expressions
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/14580.txt
- GitHubコミットページ: https://github.com/golang/go/commit/e06d90136f18fbb1ffa46537d01eb3552f45b0bc
- Go言語の公式ドキュメント (EBNFの理解のため): https://go.dev/ref/spec
- Go言語のメソッドに関する一般的な知識。
- Go言語のIssueトラッカー (Issue #4457の背景を推測するため)。