[インデックス 15] ファイルの概要
このコミットは、Go言語の初期の言語仕様ドキュメント doc/go_lang.txt
における、構造体リテラル (Struct Literal) の文法定義の重複を修正するものです。具体的には、StructType
の二重定義を解消し、StructLit
の定義をより直接的に TypeName
を参照するように変更しています。
コミット
commit f27e5df49c0fe37fab2533d93a1b2ccbe26c97b6
Author: Robert Griesemer <gri@golang.org>
Date: Thu Mar 6 22:11:51 2008 -0800
- fixed double-definition of StructType
SVN=111689
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/f27e5df49c0fe37fab2533d93a1b2ccbe26c97b6
元コミット内容
- fixed double-definition of StructType
変更の背景
Go言語の初期開発段階において、言語仕様を記述するドキュメント doc/go_lang.txt
は、言語の文法を定義するためにBNF (Backus-Naur Form) またはEBNF (Extended Backus-Naur Form) に似た形式を使用していました。このコミットが行われた時点では、StructType
という非終端記号が文法内で二重に定義されているという問題がありました。
具体的には、構造体リテラル StructLit
の定義において、StructType
を介して型を参照する形式と、TypeName
を直接参照する形式が混在していたか、あるいは StructType
自体が不必要に導入されていた可能性があります。このような二重定義は、文法の曖昧さを生み出し、パーサーの実装を複雑にするだけでなく、言語仕様の理解を困難にします。
このコミットの目的は、この文法上の重複と曖昧さを解消し、言語仕様をより明確で簡潔なものにすることでした。Go言語の設計哲学の一つに「シンプルさ」があるため、文法定義においても無駄をなくし、一貫性を持たせることは非常に重要でした。
前提知識の解説
1. BNF/EBNF (バッカス・ナウア記法 / 拡張バッカス・ナウア記法)
プログラミング言語の文法を形式的に記述するための記法です。非終端記号(構文カテゴリ、例: <expression>
)と終端記号(実際のキーワードや識別子、例: if
, +
)を用いて、言語の構造を規則の集合として表現します。
- 非終端記号: 別の規則によって定義される構文要素。通常、山括弧
< >
で囲まれるか、単に識別子として記述されます。 - 終端記号: 言語の最小単位。キーワード、演算子、識別子、リテラルなど。
- 規則 (Rule):
非終端記号 = 定義
の形式で、非終端記号がどのように構成されるかを示します。
例: Expression = Term { ("+" | "-") Term } .
2. 構造体リテラル (Struct Literal)
Go言語における構造体リテラルは、構造体の新しい値をその場で作成し、初期化するための構文です。例えば、Point{X: 10, Y: 20}
のように、構造体の型名の後に波括弧で囲まれたフィールドと値のリストが続きます。
3. 型名 (TypeName)
Go言語において、int
, string
, MyStruct
のように、特定の型を指す識別子です。
4. 文法における「二重定義」
形式文法において、同じ非終端記号が異なる規則で定義されたり、あるいは同じ概念を指す複数の非終端記号が存在し、それらが不必要に複雑な依存関係を持つ場合に「二重定義」と見なされます。これは文法の冗長性や曖昧さの原因となります。
技術的詳細
このコミットの核心は、Go言語の初期の言語仕様ドキュメント doc/go_lang.txt
内の文法規則の修正です。
修正前の文法定義は以下のようでした(コミットの差分から推測される形式):
StructLit = StructType '(' [ ExpressionList ] ')' .
StructType = TypeName .
ここで、StructLit
(構造体リテラル) は StructType
という非終端記号を使って定義されています。そして、その StructType
はさらに TypeName
(型名) として定義されています。
この定義の問題点は、StructType = TypeName .
という規則が冗長であることです。StructType
は単に TypeName
の別名として機能しており、StructLit
の定義において直接 TypeName
を使用すれば、StructType
という中間的な非終端記号は不要になります。
修正後の文法定義は以下のようになります:
StructLit = TypeName '(' [ ExpressionList ] ')' .
この変更により、以下の点が改善されます。
- 冗長性の排除:
StructType
という不必要な非終端記号が削除され、文法が簡潔になりました。 - 明確性の向上: 構造体リテラルが直接
TypeName
を参照することで、その構文がどの型に属するかがより明確になります。 - 一貫性: 言語仕様全体で、型を参照する際に
TypeName
を直接使用する一貫したパターンが確立されます。
この修正は、言語の機能そのものには影響を与えませんが、言語仕様の正確性と可読性を大幅に向上させます。特に、コンパイラやツールチェインを開発する人々にとって、明確で曖昧さのない文法定義は非常に重要です。
コアとなるコードの変更箇所
--- a/doc/go_lang.txt
+++ b/doc/go_lang.txt
@@ -623,8 +623,7 @@ Struct literals represent struct constants. They comprise a list of
expressions that represent the individual fields of a struct. The
individual expressions must match those of the specified struct type.
- StructLit = StructType '(' [ ExpressionList ] ')' .
- StructType = TypeName .
+ StructLit = TypeName '(' [ ExpressionList ] ')' .
The type name must be that of a defined struct type.
コアとなるコードの解説
この差分は、doc/go_lang.txt
ファイル内のGo言語の文法定義の一部を示しています。
- StructLit = StructType '(' [ ExpressionList ] ')' .
- これは削除された行です。以前の定義では、構造体リテラル (
StructLit
) はStructType
という非終端記号を使用して定義されていました。
- これは削除された行です。以前の定義では、構造体リテラル (
- StructType = TypeName .
- これも削除された行です。この行は
StructType
が単にTypeName
の別名であることを定義していました。この定義自体が冗長であり、StructType
がTypeName
と同じ意味を持つため、二重定義と見なされていました。
- これも削除された行です。この行は
+ StructLit = TypeName '(' [ ExpressionList ] ')' .
- これは追加された行です。新しい定義では、
StructLit
が直接TypeName
を参照するように変更されています。これにより、StructType
という中間的な非終端記号が不要になり、文法が簡潔かつ直接的になりました。
- これは追加された行です。新しい定義では、
この変更により、構造体リテラルの構文は「型名」の後に括弧と式のリストが続くという、より直感的な形式で定義されるようになりました。これは、Go言語の設計におけるシンプルさと明確さへのコミットメントを反映しています。
関連リンク
- Go言語の公式ウェブサイト: https://go.dev/
- Go言語の仕様 (現在のバージョン): https://go.dev/ref/spec
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/15.txt
- GitHubコミットページ: https://github.com/golang/go/commit/f27e5df49c0fe37fab2533d93a1b2ccbe26c97b6
- BNF/EBNFに関する一般的な知識
- Go言語の構造体リテラルに関する一般的な知識