[インデックス 1283] ファイルの概要
このコミットは、Go言語の仕様書ドラフトである doc/go_spec.txt
の変更に関するものです。このファイルは、Go言語の構文、セマンティクス、および組み込み機能の詳細を定義しており、言語設計の基礎となる重要なドキュメントです。
コミット
commit 7354b864b52fc577aa18a3a289514bc2ce58d4de
Author: Robert Griesemer <gri@golang.org>
Date: Thu Dec 4 17:33:37 2008 -0800
Revised proposal for const/var cleanup, with
Ken's suggestion for the "iota" extension to tuples.
DELTA=171 (88 added, 57 deleted, 26 changed)
OCL=20460
CL=20544
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/7354b864b52fc577aa18a3a289514bc2ce58d4de
元コミット内容
このコミットは、Go言語における定数(const
)と変数(var
)の宣言に関する仕様の改訂提案を反映しています。特に、複数の定数や変数を一度に宣言する際の構文の整理("cleanup")と、定数ジェネレータである iota
をタプル(複数の値)に拡張して適用するKen Thompson氏の提案が盛り込まれています。これにより、宣言の柔軟性と一貫性が向上し、特に列挙型のような定数群の定義がより簡潔になります。
変更の背景
この変更の背景には、Go言語の初期の仕様における定数および変数宣言のいくつかの不整合と、より表現力豊かな定数定義メカニズムへの要望がありました。コミットメッセージと差分から、以下の「Open issues」が解決されたことが示唆されます。
global var decls: "var a, b, c int = 0, 0, 0" is ok, but "var a, b, c = 0, 0, 0" is not (seems inconsistent with "var a = 0", and ":=" notation)
- これは、型指定のない複数変数宣言が許可されていなかったことに対する不整合の指摘です。単一変数宣言や短縮変数宣言(
:=
)との一貫性が求められていました。
- これは、型指定のない複数変数宣言が許可されていなかったことに対する不整合の指摘です。単一変数宣言や短縮変数宣言(
const decls: "const a, b = 1, 2" is not allowed - why not? Should be symmetric to vars.
- これは、複数の定数を一度に宣言する構文が許可されていなかったことに対する指摘です。変数宣言と同様に、複数の定数をまとめて宣言できる対称性が求められていました。
これらの課題を解決し、言語の宣言構文をより一貫性があり、直感的に使えるようにすることが変更の主な動機です。特に iota
の拡張は、C言語の enum
のような連続した定数値を生成するGoらしい強力なメカニズムを提供することを目的としています。
前提知識の解説
このコミットの変更内容を理解するためには、以下のGo言語の基本的な概念を把握しておく必要があります。
- 定数宣言 (
const
): Go言語では、const
キーワードを使用して定数を宣言します。定数はコンパイル時に値が決定され、実行時に変更することはできません。const Pi = 3.14 const Version = "1.0"
- 変数宣言 (
var
):var
キーワードを使用して変数を宣言します。変数は実行時に値を変更できます。var i int = 10 var name string = "Go"
- 短縮変数宣言 (
:=
): 関数内で変数を宣言し、初期化する際に使用できる簡潔な構文です。型推論が行われます。j := 20 // var j int = 20 と同等
iota
: Go言語の特別な定数ジェネレータです。const
ブロック内で使用され、連続する整数値を自動的に生成します。デフォルトでは0から始まり、const
ブロック内の各定数宣言ごとに1ずつ増加します。const ( A = iota // A = 0 B = iota // B = 1 C = iota // C = 2 )
- タプル代入 (Tuple Assignment): Go言語では、複数の変数に複数の値を一度に代入することができます。これは、関数の複数の戻り値を扱う際などによく使用されます。
x, y := 1, 2 // xに1、yに2を代入
技術的詳細
このコミットにおける技術的な変更の核心は、Go言語の仕様書における定数と変数の宣言構文の定義を、より柔軟で一貫性のあるものに改訂した点にあります。特に、iota
の動作が大幅に拡張され、タプル代入と組み合わせることで強力な定数生成が可能になりました。
-
ConstSpec
およびVarSpec
の統一と拡張:- 以前は、
const
宣言は単一の識別子と単一の式しか受け付けませんでした (ConstSpec = identifier [ CompleteType ] [ "=" Expression ] .
)。 - 今回の変更により、
ConstSpec
とVarSpec
の両方でIdentifierList
とExpressionList
を使用できるようになりました。ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] . VarSpec = IdentifierList ( CompleteType [ "=" ExpressionList ] | "=" ExpressionList ) . IdentifierList = identifier { "," identifier } . ExpressionList = Expression { "," Expression } .
- これにより、
const a, b = 1, 2
やvar x, y float = 0, 3
のような複数定数/変数の一括宣言が可能になり、変数宣言との対称性が確保されました。 - 型が省略された場合、定数/変数の型は対応する式の型から推論されます。型が指定された場合、すべての定数/変数はその型を持ち、式はその型に代入可能である必要があります。
- 以前は、
-
iota
の動作の明確化と拡張:iota
はconst
宣言ブロック内でのみ有効となり、その動作がより厳密に定義されました。- リセットとインクリメント:
iota
はconst
キーワードが出現するたびに0にリセットされ、各セミコロン(または暗黙のセミコロン、つまり改行)で1ずつインクリメントされます。const ( // iota は 0 にリセット enum0 = iota; // enum0 = 0 enum1 = iota; // enum1 = 1 enum2 = iota // enum2 = 2 ) const x = iota; // x = 0 (新しい const なので iota はリセット) const y = iota; // y = 0 (新しい const なので iota はリセット)
ExpressionList
内でのiota
: 最も重要な変更点の一つは、ExpressionList
(タプル代入の右辺)内でiota
が使用された場合、そのExpressionList
内のすべてのiota
の値は同じになるという点です。iota
はセミコロンでのみインクリメントされるため、単一のタプル代入内では値が固定されます。
この例では、const ( base0, mask0 int64 = 1 << iota, iota << iota - 1; // iota=0: base0=1, mask0=0 base1, mask1 int64 = 1 << iota, iota << iota - 1; // iota=1: base1=2, mask1=1 base2, mask2 int64 = 1 << iota, iota << iota - 1; // iota=2: base2=4, mask2=3 )
base0
とmask0
の計算においてiota
は両方とも0として評価されます。次の行のbase1
とmask1
の計算では、iota
は1として評価されます。
-
定数宣言における式の暗黙的な繰り返し (Implicit Repetition):
- 括弧で囲まれた
const
宣言リスト内で、最初の宣言以外のExpressionList
が省略された場合、それは直前の非空のExpressionList
のテキスト的な置換として扱われます。つまり、前の式のリストが暗黙的に繰り返されます。 - この機能は
iota
と組み合わせることで、簡潔な列挙型定義を可能にします。const ( enum0 = iota; // enum0 = 0 enum1; // enum1 = 1 (enum0 = iota が繰り返される) enum2 // enum2 = 2 (enum0 = iota が繰り返される) ) const ( a = 1 << iota; // a = 1 (iota は 0) b; // b = 2 (1 << iota が繰り返され、iota は 1) c; // c = 4 (1 << iota が繰り返され、iota は 2) )
- 括弧で囲まれた
-
短縮変数宣言 (
:=
) のタプル代入への拡張:SimpleVarDecl = identifier ":=" Expression .
からSimpleVarDecl = IdentifierList ":=" ExpressionList .
へと変更されました。- これにより、
i, j := 0, 10;
のように、短縮変数宣言でも複数の変数に複数の値を一度に代入できるようになりました。
これらの変更は、Go言語の宣言構文をより強力で、一貫性があり、そして簡潔なものにすることを目的としています。特に iota
の拡張は、Goにおける列挙型やビットフラグなどの定数群の定義において、非常にGoらしいイディオムを提供することになります。
コアとなるコードの変更箇所
このコミットは、Go言語の仕様書 doc/go_spec.txt
のみを変更しています。以下に、主要な変更箇所の差分を示します。
1. ConstDecl
の構文変更
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -661,22 +660,40 @@ A constant declaration binds an identifier to the value of a constant
expression (§Constant expressions).
ConstDecl = "const" Decl<ConstSpec> .
- ConstSpec = identifier [ CompleteType ] [ "=" Expression ] .
+ ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
+
+ IdentifierList = identifier { "," identifier } .
+ ExpressionList = Expression { "," Expression } .
2. ConstDecl
の説明と例の追加
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -661,22 +660,40 @@ A constant declaration binds an identifier to the value of a constant
expression (§Constant expressions).
ConstDecl = "const" Decl<ConstSpec> .
- ConstSpec = identifier [ CompleteType ] [ "=" Expression ] .
+ ConstSpec = IdentifierList [ CompleteType ] [ "=" ExpressionList ] .
+
+ IdentifierList = identifier { "," identifier } .
+ ExpressionList = Expression { "," Expression } .
- const pi float = 3.14159265
+A constant declaration binds a list of identifiers (the names of the constants)
+to the values of a list of constant expressions. The number of identifiers must
+be equal to the number of expressions, with the i'th identifier on the left
+corresponding to the i'th expression on the right. If CompleteType is omitted,
+the types of the constants are the types of the corresponding expressions;
+different expressions may have different types. If CompleteType is present,
+the type of all constants is the type specified, and the types of all
+expressions in ExpressionList must be assignment-compatible with the
+constant type.
+
+ const pi float64 = 3.14159265358979323846
const e = 2.718281828
const (
- one int = 1;
- two = 3
+ size int64 = 1024;
+ eof = -1;
)
+ const a, b, c = 3, 4, "foo" // a = 3, b = 4, c = "foo"
+ const u, v float = 0, 3 // u = 0.0, v = 3.0
3. 定数宣言における式の暗黙的な繰り返しに関する説明の追加
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -679,12 +696,6 @@ values:
Partyday;
)
-The initializing expression of a constant may contain only other
-constants. This is illegal:
-
- var i int = 10;
- const c = i; // error
-
The initializing expression for a numeric constant is evaluated
using the principles described in the section on numeric literals:
constants are mathematical values given a size only upon assignment
4. Iota
セクションの追加と詳細な説明
Iota
の定義が Operands
セクションから Const declarations
セクションに移動し、より詳細な動作が記述されました。
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -717,18 +728,82 @@ yields a floating point constant of value 2.5 (1.5 + 1); its
constituent expressions are evaluated using different rules for
division.
-If the type is specified, the resulting constant has the named type.
-
-If the type is missing from the constant declaration, the constant
+If the type is missing from a numeric constant declaration, the constant
represents a value of abitrary precision, either integer or floating
point, determined by the type of the initializing expression. Such
a constant may be assigned to any variable that can represent its
value accurately, regardless of type. For instance, 3 can be
-assigned to any int variable but also to any floating point variable,\n-while 1e12 can be assigned to a float32, float64, or even int64.\n-It is erroneous to assign a value with a non-zero fractional\n-part to an integer, or if the assignment would overflow or\n-underflow.\n+assigned to any integer variable but also to any floating point variable,\n+while 1e12 can be assigned to a "float32", "float64", or even "int64".\n+It is erroneous to assign a value with a non-zero fractional part\n+to an integer, or if the assignment would overflow or underflow.\n+\n+\n+Iota\n+----\n+\n+Within a constant declaration, the predeclared operand "iota" represents\n+successive elements of an integer sequence. It is reset to 0 whenever the\n+reserved word "const" appears in the source and increments with each\n+semicolon. For instance, "iota" can be used to construct a set of related\n+constants:\n+\n+\tconst ( // iota is set to 0\n+\t\tenum0 = iota; // sets enum0 to 0, etc.\n+\t\tenum1 = iota;\n+\t\tenum2 = iota\n+\t)\n+\n+\tconst (\n+\t\ta = 1 << iota; // a == 1 (iota has been reset)\n+\t\tb = 1 << iota; // b == 2\n+\t\tc = 1 << iota; // c == 4\n+\t)\n+\n+\tconst (\n+\t\tu = iota * 42; // u == 0 (ideal integer)\n+\t\tv float = iota * 42; // v == 42.0 (float)\n+\t\tw = iota * 42; // w == 84 (ideal integer)\n+\t)\n+\n+\tconst x = iota; // x == 0 (iota has been reset)\n+\tconst y = iota; // y == 0 (iota has been reset)\n+\n+Within an ExpressionList, the value of all "iota"'s is the same because "iota"\n+is only incremented at each semicolon:\n+\n+\tconst (\n+\t\tbase0, mask0 int64 = 1 << iota, iota << iota - 1; // base0 == 1, mask0 = 0\n+\t\tbase1, mask1 int64 = 1 << iota, iota << iota - 1; // base1 == 2, mask1 = 1\n+\t\tbase2, mask2 int64 = 1 << iota, iota << iota - 1; // base2 == 4, mask2 = 3\n+\t)\n+\n+Since the ExpressionList in constant declarations repeats implicitly\n+if omitted, some of the examples above can be abbreviated:\n+\n+\tconst (\n+\t\tenum0 = iota;\n+\t\tenum1;\n+\t\tenum2\n+\t)\n+\n+\tconst (\n+\t\ta = 1 << iota;\n+\t\tb;\n+\t\tc;\n+\t)\n+\n+\tconst (\n+\t\tu = iota * 42;\n+\t\tv float;\n+\t\tw;\n+\t)\n+\n+\tconst (\n+\t\tbase0, mask0 int64 = 1 << iota, iota << iota - 1;\n+\t\tbase1, mask1 int64;\n+\t\tbase2, mask2 int64;\n+\t)\n```
### 5. 短縮変数宣言 (`SimpleVarDecl`) の構文変更
```diff
--- a/doc/go_spec.txt
+++ b/doc/go_spec.txt
@@ -803,13 +875,13 @@ of the variable is "int" or "float" respectively:
The syntax
- SimpleVarDecl = identifier ":=" Expression .
+ SimpleVarDecl = IdentifierList ":=" ExpressionList .
is shorthand for
- var identifier = Expression.\n+ "var" ExpressionList = ExpressionList .\n \n-\ti := 0\n+\ti, j := 0, 10;\n \tf := func() int { return 7; }\n \tch := new(chan int);\n \t
コアとなるコードの解説
上記の差分は、Go言語の定数と変数宣言の柔軟性と表現力を大幅に向上させるための重要な変更を示しています。
-
ConstDecl
の構文変更:- 以前は単一の定数しか宣言できませんでしたが、
IdentifierList
とExpressionList
の導入により、const a, b, c = 1, 2, 3
のように複数の定数を一度に宣言できるようになりました。これは、変数宣言の構文との一貫性を高めるものです。 IdentifierList
はカンマ区切りの識別子のリストを、ExpressionList
はカンマ区切りの式のリストを意味します。これにより、タプル代入の概念が定数宣言にも適用されるようになりました。
- 以前は単一の定数しか宣言できませんでしたが、
-
ConstDecl
の説明と例の追加:- 新しい説明では、識別子のリストが定数式のリストにどのようにバインドされるかが明確にされています。識別子の数と式の数は一致する必要があり、i番目の識別子がi番目の式に対応します。
- 型が省略された場合の型推論のルール(各式の型が定数の型になる)と、型が明示された場合の型チェックのルール(すべての定数が指定された型になり、式はその型に代入可能である必要がある)が記述されています。
const a, b, c = 3, 4, "foo"
やconst u, v float = 0, 3
のような新しい例は、複数定数宣言の具体的な使用法を示しています。特に後者の例では、型が明示されているため、0
と3
がfloat
型として扱われることがわかります。
-
定数宣言における式の暗黙的な繰り返しに関する説明の追加:
- このセクションは、括弧で囲まれた
const
ブロック内で、ExpressionList
が省略された場合に、直前のExpressionList
が自動的に繰り返されるという強力な機能について説明しています。 - この機能は、特に
iota
と組み合わせることで、連続した定数値を簡潔に定義するのに役立ちます。例えば、const (A = iota; B; C)
と書くことで、B = iota
とC = iota
が暗黙的に補完され、iota
の値が自動的にインクリメントされます。
- このセクションは、括弧で囲まれた
-
Iota
セクションの追加と詳細な説明:iota
の定義が独立したセクションとして設けられ、その動作がより詳細かつ明確に記述されました。iota
がconst
キーワードの出現時に0にリセットされ、各セミコロン(または改行)でインクリメントされるというルールが強調されています。- 最も重要なのは、「
ExpressionList
内では、すべてのiota
の値は同じである」というルールです。これは、iota
がセミコロンでのみインクリメントされるため、単一のタプル代入内ではiota
の値が固定されることを意味します。これにより、base0, mask0 int64 = 1 << iota, iota << iota - 1
のような複雑な定数定義が可能になります。 - 暗黙的な繰り返しと
iota
を組み合わせた簡潔な列挙型の例が多数追加され、その強力な表現力が示されています。
-
短縮変数宣言 (
SimpleVarDecl
) の構文変更:i := 0
のような単一の短縮変数宣言だけでなく、i, j := 0, 10;
のように複数の変数に複数の値を一度に代入するタプル代入が:=
構文でも可能になりました。これにより、変数宣言のすべての形式でタプル代入がサポートされ、一貫性が向上しました。
これらの変更は、Go言語の定数と変数宣言の構文をより洗練させ、特に iota
を用いた定数定義のイディオムを確立する上で極めて重要な役割を果たしました。
関連リンク
- Go Programming Language Specification: https://go.dev/ref/spec (現在のGo言語仕様)
- Go Language Design Documents: https://go.dev/doc/go_language_design.html (Go言語の設計に関するドキュメント)
参考にした情報源リンク
- コミット情報:
/home/orange/Project/comemo/commit_data/1283.txt
- Go言語の仕様に関する一般的な知識。
- Go言語の
const
とiota
に関する一般的な知識。