[インデックス 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
daebf91d2c0e719a7b59ba1c26ccc8def83e39bc
https://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) に関する一般的な情報