Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 1818] ファイルの概要

このコミットは、Go言語の仕様書(doc/go_spec.html)における数値リテラルの型の決定に関する記述を修正するものです。具体的には、「理想的な整数(ideal integer)」または「理想的な浮動小数点数(ideal float)」の型が、その値が正確に整数として表現できるかどうかではなく、リテラルの構文によって決定されることを明確にしています。

コミット

commit ce9417ee1a2bb90fca34c87dc4f7516dfb5519b5
Author: Rob Pike <r@golang.org>
Date:   Thu Mar 12 17:08:47 2009 -0700

    fix language regarding type of numeric literals
    
    R=rsc
    DELTA=4  (0 added, 2 deleted, 2 changed)
    OCL=26208
    CL=26212

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/ce9417ee1a2bb90fca34c87dc4f7516dfb5519b5

元コミット内容

    fix language regarding type of numeric literals
    
    R=rsc
    DELTA=4  (0 added, 2 deleted, 2 changed)
    OCL=26208
    CL=26212

変更の背景

このコミットは、Go言語の初期段階における仕様策定の一環として行われました。Go言語は、C言語のような低レベルなプログラミングと、PythonやJavaScriptのような高レベルなプログラミングの利点を組み合わせることを目指していました。その中で、数値リテラルの扱い、特にその型推論は、言語の使いやすさと厳密性のバランスを取る上で重要な要素でした。

初期のGo言語の設計では、数値リテラルは特定の型を持たず、「理想的な(ideal)」型として扱われるという概念がありました。これは、リテラルが使用される文脈に応じて、適切な具体的な型に変換されることを意味します。例えば、123というリテラルは、int型の変数に代入されればint型として、float64型の変数に代入されればfloat64型として扱われる、といった具合です。

しかし、この「理想的な」型の決定ロジック、特に整数リテラルと浮動小数点リテラルの区別について、仕様書の記述が曖昧であったり、誤解を招く可能性がありました。元の記述では、「値が正確に整数として表現できるかどうか」で理想的な整数か浮動小数点かが決まるかのようなニュアンスがありましたが、これはGo言語の設計思想とは異なりました。Go言語では、リテラルの構文(例: 123は整数、123.0は浮動小数点数)がその「理想的な」型を決定する主要な要因です。

このコミットは、この誤解を解消し、Go言語の数値リテラルの型決定ルールをより正確に反映させるために行われました。これにより、開発者がGo言語の数値リテラルをどのように解釈し、使用すべきかについて、より明確な指針が提供されることになります。

前提知識の解説

Go言語の数値リテラルと型システム

Go言語の型システムは静的型付けであり、変数は宣言時に型を持ちます。しかし、数値リテラル(例: 10, 3.14, 0xFF)は、初期の段階では特定の具象型を持ちません。代わりに、これらは「型なし定数(untyped constants)」として扱われます。

理想的な整数(Ideal Integer)と理想的な浮動小数点数(Ideal Float)

Go言語の型なし定数には、「理想的な整数(ideal integer)」と「理想的な浮動小数点数(ideal float)」という概念があります。

  • 理想的な整数(Ideal Integer): 整数リテラル(例: 10, 0xFF)は、その値がどんなに大きくても、オーバーフローすることなく表現できるかのように扱われます。これは、コンパイル時にその値が使用される文脈(例えば、int型やint64型など)に応じて、適切な具象型に変換されるためです。
  • 理想的な浮動小数点数(Ideal Float): 浮動小数点リテラル(例: 3.14, 1.0e-9)も同様に、その値がどんなに精度が高くても、オーバーフローや精度損失なしに表現できるかのように扱われます。これもまた、コンパイル時にfloat32型やfloat64型などに変換されます。

この「理想的な」という概念は、プログラマがリテラルを記述する際に、具体的な数値型の制約を意識することなく、より自然に数値を扱えるようにするためのものです。コンパイラが文脈に基づいて最適な型を推論し、必要に応じて変換を行います。

型なし定数の型決定ルール

型なし定数が具体的な型を持つのは、以下のいずれかの状況です。

  1. 変数への代入: 型付きの変数に代入される場合、定数はその変数の型に変換されます。
    var i int = 10 // 10 は int 型に変換される
    var f float64 = 3.14 // 3.14 は float64 型に変換される
    
  2. 型変換: 明示的に型変換される場合。
    x := float32(10) // 10 は float32 型に変換される
    
  3. 演算: 演算の文脈で、オペランドの型に基づいて型が決定される場合。
    var a int = 5
    b := a + 10 // 10 は int 型に変換される
    
  4. デフォルトの型: 上記のいずれにも該当しない場合(例: fmt.Println(10))、定数にはデフォルトの型が適用されます。整数リテラルのデフォルトはint、浮動小数点リテラルのデフォルトはfloat64です。

このコミットの変更は、特に「理想的な整数」と「理想的な浮動小数点数」の区別が、その値の表現可能性ではなく、リテラルの構文によって決まるという点を明確にしています。

技術的詳細

このコミットの技術的な核心は、Go言語のコンパイラが数値リテラルをどのように解釈し、その「理想的な」型を決定するかという点にあります。

Go言語の仕様では、数値リテラルは以下の構文規則に従います。

  • 整数リテラル: 数字の並びで構成され、小数点や指数部を含みません(例: 123, 0xAF, 0o77, 0b101)。
  • 浮動小数点リテラル: 小数点(.)または指数部(eまたはE)を含む数字の並びで構成されます(例: 123.0, 1.23e+5, .5, 1.)。

このコミット以前の仕様書の記述は、数値リテラルの型が「値が正確に整数として表現できるかどうか」に依存するかのような誤解を招く可能性がありました。例えば、1.0という浮動小数点リテラルは、値としては整数1と等価ですが、構文的には浮動小数点リテラルです。Go言語の設計では、このような場合でも1.0は「理想的な浮動小数点数」として扱われるべきであり、「理想的な整数」とは異なる振る舞いをします。

このコミットは、この点を明確にするために、以下の変更を加えています。

  • 変更前: 「それが整数か浮動小数点数かは、値が正確に整数として表現できるかどうかに依存する(123 vs. 1.23)。」
  • 変更後: 「リテラルが整数か浮動小数点数かは、リテラルの構文に依存する(123 vs. 123.0)。」

この修正により、Go言語のコンパイラが数値リテラルを構文的に解析し、その結果に基づいて「理想的な」型を決定するという、実際の動作がより正確に反映されるようになりました。これは、コンパイラの設計と実装、そしてGo言語の型システムの整合性を保つ上で重要な変更です。

例えば、3/2という式では、32はどちらも整数リテラルであるため、「理想的な整数」として扱われ、結果は整数除算の1になります。一方、3./2.という式では、3.2.は浮動小数点リテラルであるため、「理想的な浮動小数点数」として扱われ、結果は浮動小数点除算の1.5になります。この挙動は、リテラルの構文によって型が決定されるというルールに基づいています。

この変更は、Go言語の初期の仕様策定段階における、言語のセマンティクスを正確に文書化するための継続的な努力の一部です。

コアとなるコードの変更箇所

変更はdoc/go_spec.htmlファイル内で行われています。

--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -2856,10 +2856,8 @@ In practice, constant expressions are those that can be evaluated at compile tim
 <p>
 The type of a constant expression is determined by the type of its
 elements.  If it contains only numeric literals, its type is <i>ideal
-integer</i> or <i>ideal float</i> (§Ideal number).  Whether it is an
-integer or float depends on whether the value can be represented
-precisely as an integer (123 vs. 1.23).
-(TODO: Not precisely true; 1. is an ideal float.)
+integer</i> or <i>ideal float</i> (§Ideal number).  Whether a literal
+is an integer or float depends on the syntax of the literals (123 vs. 123.0).
 The nature of the arithmetic
 operations within the expression depends, elementwise, on the values;
 for example, 3/2 is an integer division yielding 1, while 3./2. is

コアとなるコードの解説

変更された行は、Go言語の仕様書における「定数式(constant expressions)」の型決定に関するセクションです。

元の記述は以下の通りでした。

The type of a constant expression is determined by the type of its
elements.  If it contains only numeric literals, its type is <i>ideal
integer</i> or <i>ideal float</i> (§Ideal number).  Whether it is an
integer or float depends on whether the value can be represented
precisely as an integer (123 vs. 1.23).
(TODO: Not precisely true; 1. is an ideal float.)

この部分では、定数式が数値リテラルのみを含む場合、その型は「理想的な整数」または「理想的な浮動小数点数」になると説明しています。しかし、その後の文で「それが整数か浮動小数点数かは、値が正確に整数として表現できるかどうかに依存する(123 vs. 1.23)」と記述されており、これが誤解を招く可能性がありました。特に、1.のような浮動小数点リテラルが、値としては整数1と等価であるにもかかわらず、「理想的な浮動小数点数」として扱われるという矛盾が、TODOコメントで指摘されています。

このコミットによって、この部分が以下のように修正されました。

The type of a constant expression is determined by the type of its
elements.  If it contains only numeric literals, its type is <i>ideal
integer</i> or <i>ideal float</i> (§Ideal number).  Whether a literal
is an integer or float depends on the syntax of the literals (123 vs. 123.0).

変更点は以下の通りです。

  1. Whether it is an integer or float depends on whether the value can be represented precisely as an integer (123 vs. 1.23). が削除されました。
  2. Whether a literal is an integer or float depends on the syntax of the literals (123 vs. 123.0). が追加されました。
  3. (TODO: Not precisely true; 1. is an ideal float.) のコメントが削除されました。

この修正により、数値リテラルが「理想的な整数」になるか「理想的な浮動小数点数」になるかは、そのが整数として正確に表現できるかどうかではなく、リテラルの構文(小数点が含まれるか、指数部が含まれるかなど)によって決定されるという、Go言語の正確なセマンティクスが明確に示されました。

例えば、123は整数リテラル構文なので「理想的な整数」となり、123.0は浮動小数点リテラル構文なので「理想的な浮動小数点数」となります。この区別は、Go言語における定数式の評価や型推論において非常に重要です。

関連リンク

  • Go言語の仕様書(現在のバージョン): https://go.dev/ref/spec
    • 特に「Constants」のセクションを参照すると、数値リテラルと型なし定数に関する最新の記述を確認できます。

参考にした情報源リンク

  • Go言語の公式ドキュメント
  • Go言語のGitHubリポジトリのコミット履歴
  • Go言語の初期の設計に関する議論やメーリングリストのアーカイブ(一般公開されているもの)
  • Go言語の型システムに関する技術記事や解説
  • Go言語のコンパイラに関する情報