[インデックス 177] ファイルの概要
このコミットは、Go言語の初期の仕様書である doc/go_lang.txt における if および switch ステートメントの文法定義を修正し、より正確かつ柔軟な記述を可能にするものです。特に、これらの制御構造におけるオプション要素(初期化ステートメントや条件式)の扱いが明確化されています。
コミット
commit daebf91d2c0e719a7b59ba1c26ccc8def83e39bc
Author: Rob Pike <r@golang.org>
Date: Mon Jun 16 12:02:27 2008 -0700
fix up grammar for optional elements in if and switch conditions
SVN=122915
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/daebf91d2c0e719a7b59ba1c26ccc8def83e39bc
元コミット内容
fix up grammar for optional elements in if and switch conditions
このコミットメッセージは、if および switch ステートメントにおけるオプション要素(条件式や初期化ステートメント)の文法定義を修正したことを簡潔に示しています。SVN=122915 は、この変更がGo言語のリポジトリがGitに移行する前のSubversionリビジョン122915に由来することを示しています。
変更の背景
Go言語は設計段階から簡潔さと実用性を重視しており、その文法も進化を続けていました。このコミットが行われた2008年6月は、Go言語がまだ一般に公開される前の初期開発段階にあたります。この時期には、言語仕様の細部が頻繁に議論され、調整されていました。
if や switch ステートメントにおける初期化ステートメント(SimpleStat)や条件式の扱いは、コードの記述性や可読性に大きく影響します。初期の文法定義には、これらのオプション要素の記述に関して曖昧さや、意図しない制約があった可能性があります。
具体的には、以下の点が背景にあると考えられます。
- 文法定義の明確化:
doc/go_lang.txtはGo言語の公式な仕様書であり、その文法定義は厳密である必要があります。初期の定義が、実際の言語の挙動や設計思想と完全に一致していなかった、あるいは誤解を招く可能性があったため、より正確な記述が求められました。 ifステートメントにおける条件の省略: Go言語のifステートメントでは、条件式を省略した場合にtrueとみなされるという特徴があります。しかし、初期化ステートメントが伴う場合にこの省略が許されるかどうかが不明確だった可能性があります。このコミットは、初期化ステートメントがあっても条件を省略できる(そしてtrueとみなされる)という挙動を明確にするために行われました。switchステートメントにおける式の省略: Go言語のswitchステートメントには、式を伴わない「裸のswitch」(bare switch)という形式があります。これは、case句がブール式を評価するif-else ifの連鎖のような振る舞いをします。初期の文法定義では、この「裸のswitch」の形式が十分に表現されていなかったか、あるいはそのオプション性が明確でなかった可能性があります。
これらの背景から、Go言語の設計者たちは、より一貫性があり、かつ柔軟な制御フローの記述を可能にするために、文法定義の修正を行ったと考えられます。
前提知識の解説
このコミットの変更内容を理解するためには、Go言語における以下の基本的な文法と概念を理解しておく必要があります。
1. Go言語の if ステートメント
Go言語の if ステートメントは、他の多くのC系言語と似ていますが、いくつかの特徴があります。
- 括弧の省略: 条件式を括弧で囲む必要はありません。
- 波括弧の必須:
thenブロックは必ず波括弧{}で囲む必要があります。 - 初期化ステートメント:
ifステートメントの条件式の前に、セミコロン;で区切って短い初期化ステートメント(SimpleStat)を記述できます。ここで宣言された変数のスコープは、ifステートメント全体(elseブロックを含む)に限定されます。 例:if x := f(); x < y { ... } - 条件の省略: 条件式を省略した場合、その条件は
trueとみなされます。これはforループの条件省略と同様の挙動です。 例:if { ... }は常に実行されます。
2. Go言語の switch ステートメント
Go言語の switch ステートメントも特徴的です。
- 括弧の省略:
switch式を括弧で囲む必要はありません。 breakの不要: 各case句の最後にbreakステートメントを明示的に記述する必要はありません。Goでは、caseがマッチするとそのブロックが実行され、自動的にswitchステートメントを抜けます。fallthrough: 意図的に次のcase句に処理を継続させたい場合は、fallthroughキーワードを使用します。- 初期化ステートメント:
ifと同様に、switch式の前に初期化ステートメントを記述できます。 - 式の省略(Bare Switch):
switchキーワードの後に式を記述しない「裸のswitch」が可能です。この場合、各case句はブール式を評価し、最初にtrueとなったcaseのブロックが実行されます。これはif-else if-elseの連鎖をより簡潔に記述するのに役立ちます。 例:switch { case x < 0: // ... case x == 0: // ... default: // ... } - 型スイッチ:
switchステートメントは、インターフェース変数の動的な型をチェックするためにも使用できます。
3. 文法定義の表記
doc/go_lang.txt のような言語仕様書では、文法規則を記述するためにバッカス・ナウア記法(BNF)に似た形式が用いられます。
=: 定義|: または (選択肢)[ ... ]: オプション(0回または1回出現){ ... }: 0回以上の繰り返し"...": リテラル(キーワードなど)Name: 非終端記号(別の文法規則で定義される要素)
この表記法を理解することで、コミットで変更された文法規則の意味を正確に読み解くことができます。
技術的詳細
このコミットは、doc/go_lang.txt 内の IfStat (If statements) と SwitchStat (Switch statements) の文法定義を修正しています。
IfStat の変更点
1. 文法規則の変更
変更前:
IfStat = "if" [ [ SimpleStat ";" ] Expression ] Block [ "else" Statement ] .
変更後:
IfStat = "if" [ [ Simplestat ] ";" ] [ Condition ] Block [ "else" Statement ] .
この変更には以下の意図があります。
ExpressionからConditionへの変更:Expressionは一般的な式を指しますが、Conditionはより具体的にブール値を評価する式を指します。これは、ifステートメントの文脈において、その位置に期待されるものが「条件」であることを明確にするためのセマンティックな変更です。Go言語では、ifの条件は常にブール値でなければなりません。[ SimpleStat ";" ]の表記の明確化: 変更前は[ [ SimpleStat ";" ] Expression ]のように、SimpleStatとセミコロンがセットでオプションであることを示していました。変更後は[ [ Simplestat ] ";" ]となり、Simplestat自体がオプションであり、もし存在すればセミコロンが続く、という構造をより明確に表現しています。これは、SimpleStatが存在しない場合でもセミコロンが続く可能性を示唆するものではなく、SimpleStatがあればセミコロンが必須であることを示しています。
2. 説明文の変更
変更前:
The condition may be omitted in which
If a variable is declared, the condition cannot be omitted.
変更後:
The condition may be omitted, in which
the variable is initialized once before the statement is entered.
この説明文の変更は非常に重要です。
- 「The condition may be omitted in which」から「The condition may be omitted, in which」: これは単なる句読点の修正であり、文法的な意味合いの変更はありませんが、文章の可読性を向上させています。
- 「If a variable is declared, the condition cannot be omitted.」の削除:
この文の削除は、Go言語の
ifステートメントの挙動における重要な変更を示唆しています。変更前は、「ifステートメントで変数を宣言した場合(例:if x := f(); ...)、条件式を省略することはできない」とされていました。しかし、この文が削除されたことにより、変数を宣言した場合でも条件式を省略できるようになったことを意味します。 Go言語のifステートメントでは、条件式が省略された場合、その条件はtrueとみなされます。したがって、この変更により、if x := f(); { ... }のような形式が有効になり、f()の結果をxに代入しつつ、常にブロックを実行するという記述が可能になりました。これは、forループのfor { ... }(無限ループ) と同様の「条件省略時はtrue」という一貫した設計思想をifステートメントにも適用したものです。
SwitchStat の変更点
1. 文法規則の変更
変更前:
SwitchStat = "switch" [ [ SimpleStat ";" ] Expression ] "{" { CaseClause } "}" .
変更後:
SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" .
この変更も IfStat と同様に、[ SimpleStat ";" ] の表記が [ Simplestat ] ";" ] に修正され、SimpleStat のオプション性がより明確に表現されています。
さらに重要なのは、Expression が [ Expression ] となり、switch ステートメントの式がオプションになったことです。
Expressionから[ Expression ]への変更: これにより、switchキーワードの後に式を記述しない「裸のswitch」(bare switch)が文法的に正式に認められたことを意味します。裸のswitchでは、各case句がブール式を評価し、最初にtrueとなったcaseのブロックが実行されます。これは、複数の条件をif-else ifの連鎖で記述するよりも、構造的に整理されたコードを書くことを可能にします。
まとめ
このコミットは、Go言語の if および switch ステートメントの文法定義を、より正確で柔軟なものに修正しました。
ifステートメントでは、初期化ステートメントが存在する場合でも条件式を省略できる(そしてtrueとみなされる)ようになりました。switchステートメントでは、式を省略した「裸のswitch」が正式に文法として認められました。
これらの変更は、Go言語の制御フロー構造の設計における一貫性と表現力を向上させるものであり、言語の成熟に向けた重要な一歩と言えます。
コアとなるコードの変更箇所
変更は doc/go_lang.txt ファイルのみです。
--- a/doc/go_lang.txt
+++ b/doc/go_lang.txt
@@ -1582,10 +1582,10 @@ If statements
If statements have the traditional form except that the
condition need not be parenthesized and the "then" statement
-must be in brace brackets. The condition may be omitted in which
+must be in brace brackets. The condition may be omitted, in which
case it is assumed to have the value "true".
- IfStat = "if" [ [ SimpleStat ";" ] Expression ] Block [ "else" Statement ] .
+ IfStat = "if" [ [ Simplestat ] ";" ] [ Condition ] Block [ "else" Statement ] .
if x > 0 {\n return true;\n
@@ -1593,8 +1593,7 @@ case it is assumed to have the value "true".
An "if" statement may include the declaration of a single temporary variable.\n The scope of the declared variable extends to the end of the if statement, and\n-the variable is initialized once before the statement is entered. If a variable\n-is declared, the condition cannot be omitted.\n+the variable is initialized once before the statement is entered.\n \n if x := f(); x < y {\n return x;\n@@ -1610,7 +1609,7 @@ Switch statements
Switches provide multi-way execution.\n
- SwitchStat = "switch" [ [ SimpleStat ";" ] Expression ] "{" { CaseClause } "}" .
+ SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" .
CaseClause = CaseList StatementList [ ";" ] [ "fallthrough" [ ";" ] ] .
CaseList = Case { Case } .
Case = ( "case" ExpressionList | "default" ) ":" .
コアとなるコードの解説
このコミットは、Go言語の文法定義を記述したドキュメントファイル doc/go_lang.txt のみを変更しています。実際のコンパイラやランタイムのコードを変更するものではありませんが、言語の挙動に関する公式な記述を修正することで、Go言語の仕様を明確にしています。
IfStat の変更
IfStat = "if" [ [ SimpleStat ] ";" ] [ Condition ] Block [ "else" Statement ] .[ SimpleStat ";" ]から[ Simplestat ] ";" ]への変更は、SimpleStat(初期化ステートメント)がオプションであり、もし存在すればセミコロンが続く、という文法構造をより正確に表現しています。ExpressionからConditionへの変更は、ifステートメントのこの位置にはブール値を評価する「条件」が来ることが期待されるという、セマンティックな明確化です。
If a variable is declared, the condition cannot be omitted.の削除- この行の削除が、
ifステートメントの挙動における最も重要な変更点です。これにより、ifステートメントで変数を宣言した場合(例:if x := f(); ...)でも、条件式を省略できる(そしてtrueとみなされる)ようになりました。 - 例:
if x := f(); { fmt.Println(x) }のようなコードが有効になります。これはf()を実行してxに代入し、常にfmt.Println(x)を実行するという意味になります。
- この行の削除が、
SwitchStat の変更
SwitchStat = "switch" [ [ Simplestat ] ";" ] [ Expression ] "{" { CaseClause } "}" .[ SimpleStat ";" ]から[ Simplestat ] ";" ]への変更はIfStatと同様です。Expressionから[ Expression ]への変更は、switchステートメントの式がオプションになったことを意味します。これにより、switchキーワードの後に式を記述しない「裸のswitch」(bare switch)が文法的に正式に認められました。- 例:
switch { case x > 0: ... }のようなコードが有効になります。これは、case句がブール式を評価するif-else ifのような振る舞いをします。
これらの変更は、Go言語の初期開発段階における言語仕様の洗練と、より一貫性のある、かつ表現力の高い制御フロー構造の提供を目指したものです。ドキュメントの修正ではありますが、これはGo言語の文法がどのように進化していったかを示す重要な記録です。
関連リンク
- Go言語公式ドキュメント: https://go.dev/doc/
- Go言語の
ifステートメントに関する公式ドキュメント(現在のバージョン): https://go.dev/ref/spec#If_statements - Go言語の
switchステートメントに関する公式ドキュメント(現在のバージョン): https://go.dev/ref/spec#Switch_statements
参考にした情報源リンク
- GitHub: golang/go commit
daebf91d2c0e719a7b59ba1c26ccc8def83e39bchttps://github.com/golang/go/commit/daebf91d2c0e719a7b59ba1c26ccc8def83e39bc - Go言語の初期の歴史に関する情報(Go言語の設計思想や進化を理解する上で参考になります)
- The Go Programming Language Specification (current): https://go.dev/ref/spec
- Effective Go: https://go.dev/doc/effective_go
- Go at Google: Language Design in the Service of Software Engineering: https://go.dev/talks/2012/go4procs.slide#1 (Go言語の設計哲学に関する講演資料)
- バッカス・ナウア記法 (BNF) に関する一般的な情報