[インデックス 14631] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html)における定数式の例に関するコメントを、より明確で詳細なものに修正することを目的としています。特に、定数の型と値、および定数式が評価される際の挙動について、読者の理解を深めるための情報が追加されています。
コミット
commit 462860bd8db134859809ea2cd6b063a0f767ea38
Author: Robert Griesemer <gri@golang.org>
Date: Wed Dec 12 14:25:40 2012 -0800
spec: more explicit comments for constant expression examples
Fixes #3814.
R=rsc, iant
CC=golang-dev
https://golang.org/cl/6920057
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/462860bd8db134859809ea2cd6b063a0f767ea38
元コミット内容
定数式の例に関するコメントをより明示的にする。 Issue #3814 を修正。
変更の背景
このコミットの背景には、Go言語の定数式の挙動、特に「型なし定数(untyped constant)」と「型付き定数(typed constant)」の間の相互作用、およびそれらがどのように評価され、型付けされるかについての理解を深めるという目的があります。Go言語の定数は、その柔軟性と強力さゆえに、初心者にとっては理解が難しい場合があります。特に、大きな数値や複素数、ビット演算を含む定数式が、どのような型で、どのような値を持つのかを明確にすることは重要です。
コミットメッセージにある "Fixes #3814" は、GoのIssueトラッカーに登録されていた問題(おそらく定数式の例に関する説明の不明瞭さや誤解を招く可能性)を解決するためのものであることを示唆しています。仕様書は言語の最終的な権威であるため、その記述は極めて正確かつ明確である必要があります。このコミットは、その目標を達成するために、既存の例に対するコメントを詳細化し、読者が定数式の評価結果と型を正確に把握できるように改善しています。
前提知識の解説
このコミットの変更内容を理解するためには、Go言語における以下の概念を理解しておく必要があります。
-
定数 (Constants):
- Go言語の定数は、コンパイル時に値が決定される不変のエンティティです。数値、真偽値、文字列の定数があります。
- 型なし定数 (Untyped Constants): Goの定数の特徴的な点の一つは、デフォルトで「型なし」であることです。型なし定数は、その値が表現できる任意の型に暗黙的に変換できます。これにより、異なる数値型間での演算が柔軟に行えます。例えば、
const x = 1のxは型なし整数定数であり、int,int32,float64など、様々な数値型に代入できます。 - 型付き定数 (Typed Constants): 定数に明示的に型が指定された場合(例:
const x int = 1)、その定数は型付き定数となり、その型に厳密に従います。型付き定数は、同じ型の変数にのみ代入できます。 - 定数式 (Constant Expressions): 定数のみを含む式は、コンパイル時に評価され、結果も定数となります。定数式の結果が型なし定数になるか、型付き定数になるかは、式に含まれる定数の型によって決まります。
-
複素数 (Complex Numbers):
- Go言語は組み込みで複素数型(
complex64とcomplex128)をサポートしています。 complex(real, imag)関数は、実部と虚部から複素数を生成します。引数が型なし定数であれば、結果も型なし複素数定数になります。
- Go言語は組み込みで複素数型(
-
ビットシフト演算子 (Bit Shift Operators):
<<(左シフト) と>>(右シフト) は、ビット単位で数値をシフトする演算子です。1 << 100のような式は、1を100ビット左にシフトすることを意味し、非常に大きな整数定数を生成します。Goの型なし整数定数は、任意の精度を持つため、通常の整数型では表現できないような巨大な値も保持できます。
-
型の表現範囲 (Type Range):
- Goの各数値型(
int8,uint8,int64など)には、表現できる値の範囲が厳密に定められています。 - 定数式の結果が、代入先の型の表現範囲を超える場合、コンパイルエラーとなります。例えば、
int8は -128 から 127 までの値しか表現できません。
- Goの各数値型(
技術的詳細
このコミットは、Go言語の仕様書内の定数式の例に、より詳細なコメントを追加することで、読者が各定数式の評価結果(値と型)を正確に理解できるようにしています。具体的には、以下の点が改善されています。
-
複素数定数の例の明確化:
const ic = complex(0, c)の例では、cが型なし浮動小数点定数であるため、icも「型なし複素数定数」となることが明示されました。const iΘ = complex(0, Θ)の例では、Θが型付きのcomplex128定数であるため、iΘも「complex128型」となることが明示されました。これにより、引数の型が結果の定数の型にどのように影響するかが明確になります。
-
巨大な整数定数の例の明確化:
const Huge = 1 << 100の例では、Hugeが「型なし整数定数」であり、その具体的な値(1267650600228229401496703205376)がコメントに追記されました。Goの型なし整数定数が、通常の整数型では表現できないほどの精度を持つことが強調されています。const Four int8 = Huge >> 98の例では、Fourが「int8型」であり、その値が4であることが明示されました。巨大な型なし整数定数が、型付きの小さな整数型にどのように収まるかを示しています。
-
不正な定数式の例の理由の明確化:
int64(Huge)が不正である理由として、1<<100の具体的な値がint64の表現範囲を超えていることが明示されました。Four * 300が不正である理由として、オペランド300がFourの型(int8)で表現できないことが明示されました。Four * 100が不正である理由として、積400がFourの型(int8)で表現できないことが明示されました。uint8(^1)が不正である理由として、^1の結果である-2がuint8で表現できないことが明示されました。
これらの変更は、単にコメントを追加するだけでなく、Go言語の定数に関する深い理解を促すための重要な改善です。特に、型なし定数の「任意の精度」という特性と、型付き定数への変換時の型の表現範囲チェックの重要性が、具体的な数値と型情報によって強調されています。
コアとなるコードの変更箇所
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -3706,8 +3706,8 @@ an untyped complex constant.
</p>
<pre>
-const ic = complex(0, c) // ic == 3.75i (untyped complex constant)
-const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128)
+const ic = complex(0, c) // ic == 3.75i (untyped complex constant)
+const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128)
</pre>
<p>
@@ -3717,8 +3717,8 @@ by any predeclared type in the language. The following are legal declarations:\n </p>\n
<pre>
-const Huge = 1 << 100
-const Four int8 = Huge >> 98
+const Huge = 1 << 100 // Huge == 1267650600228229401496703205376 (untyped integer constant)
+const Four int8 = Huge >> 98 // Four == 4 (type int8)\n </pre>
<p>
@@ -3737,9 +3737,9 @@ of the constant type. The following constant expressions are illegal:\n <pre>
uint(-1) // -1 cannot be represented as a uint
int(3.14) // 3.14 cannot be represented as an int
-int64(Huge) // 1<<100 cannot be represented as an int64
-Four * 300 // 300 cannot be represented as an int8
-Four * 100 // 400 cannot be represented as an int8
+int64(Huge) // 1267650600228229401496703205376 cannot be represented as an int64
+Four * 300 // operand 300 cannot be represented as an int8 (type of Four)\n+Four * 100 // product 400 cannot be represented as an int8 (type of Four)\n </pre>
<p>
@@ -3750,7 +3750,7 @@ and -1 for signed and untyped constants.\n
<pre>
^1 // untyped integer constant, equal to -2
-uint8(^1) // error, same as uint8(-2), out of range
+uint8(^1) // illegal: same as uint8(-2), -2 cannot be represented as a uint8\n ^uint8(1) // typed uint8 constant, same as 0xFF ^ uint8(1) = uint8(0xFE)\n int8(^1) // same as int8(-2)\n ^int8(1) // same as -1 ^ int8(1) = -2
コアとなるコードの解説
上記の差分は、Go言語の仕様書(doc/go_spec.html)内の定数式の例に対するコメントの変更を示しています。
-
複素数定数の例:
- const ic = complex(0, c) // ic == 3.75i (untyped complex constant)+ const ic = complex(0, c) // ic == 3.75i (untyped complex constant)- コメントのスペースが調整され、視認性が向上しています。意味的な変更はありません。
- const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128)+ const iΘ = complex(0, Θ) // iΘ == 1.5i (type complex128)- こちらもコメントのスペース調整です。
-
巨大な整数定数の例:
- const Huge = 1 << 100+ const Huge = 1 << 100 // Huge == 1267650600228229401496703205376 (untyped integer constant)Huge定数の具体的な値 (1267650600228229401496703205376) と、それが「型なし整数定数」であるという情報が追加されました。これにより、Goの型なし定数が任意の精度を持つことが明確に示されます。
- const Four int8 = Huge >> 98+ const Four int8 = Huge >> 98 // Four == 4 (type int8)Four定数の具体的な値 (4) と、それが「int8型」であるという情報が追加されました。巨大な型なし整数定数から、型付きの小さな整数定数がどのように導かれるかが明確になります。
-
不正な定数式の例:
- int64(Huge) // 1<<100 cannot be represented as an int64+ int64(Huge) // 1267650600228229401496703205376 cannot be represented as an int64Hugeの具体的な値がint64で表現できないことが明示され、より分かりやすくなりました。
- Four * 300 // 300 cannot be represented as an int8+ Four * 300 // operand 300 cannot be represented as an int8 (type of Four)300がint8で表現できないという理由に加えて、「Fourの型(int8)のオペランドとして」という文言が追加され、より正確な理由が示されています。
- Four * 100 // 400 cannot be represented as an int8+ Four * 100 // product 400 cannot be represented as an int8 (type of Four)400がint8で表現できないという理由に加えて、「Fourの型(int8)の積として」という文言が追加され、演算結果が型の範囲を超えることが明確に示されています。
- uint8(^1) // error, same as uint8(-2), out of range+ uint8(^1) // illegal: same as uint8(-2), -2 cannot be represented as a uint8- 「error」から「illegal」に変更され、より一般的な表現になりました。また、「out of range」が「-2 cannot be represented as a uint8」と具体的に記述され、エラーの理由が明確化されました。
これらの変更は、Go言語の定数に関する仕様の理解を深める上で、非常に有用な情報を提供しています。特に、型なし定数の挙動と、型変換時の範囲チェックの重要性が強調されています。
関連リンク
- GitHubコミットページ: https://github.com/golang/go/commit/462860bd8db134859809ea2cd6b063a0f767ea38
- Go CL (Code Review): https://golang.org/cl/6920057
参考にした情報源リンク
- Go Language Specification: https://go.dev/ref/spec (特に "Constants" のセクション)