[インデックス 10820] ファイルの概要
このコミットは、Go言語の仕様書(doc/go_spec.html
)における記述の明確化を目的としています。特に、「複数行にわたる (spanning multiple lines)」という曖昧な表現を、「改行を含む (containing newlines)」または「改行 (newline)」というより厳密な用語に置き換えることで、仕様の正確性を向上させています。
コミット
commit 11b7c89b262c41ce53d4ac936fce13ae1488c5d0
Author: Robert Griesemer <gri@golang.org>
Date: Thu Dec 15 10:51:51 2011 -0800
go spec: be precise about newlines
Several places mentioned tokens spanning "multiple lines"
which is not a well-defined term in the spec; newline is.
R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/5490046
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/11b7c89b262c41ce53d4ac936fce13ae1488c5d0
元コミット内容
go spec: be precise about newlines
Several places mentioned tokens spanning "multiple lines"
which is not a well-defined term in the spec; newline is.
R=golang-dev, rsc, r
CC=golang-dev
https://golang.org/cl/5490046
変更の背景
プログラミング言語の仕様書は、その言語の挙動を正確かつ曖昧さなく定義する非常に重要な文書です。特に、字句解析(lexical analysis)や構文解析(parsing)に関する記述は、コンパイラやインタプリタの実装に直接影響するため、厳密な用語の使用が求められます。
このコミットが行われた2011年12月時点のGo言語仕様書には、「複数行にわたる (spanning multiple lines)」という表現がいくつか存在していました。しかし、この表現は形式的な仕様の文脈においては曖昧であり、正確な定義が不足していました。例えば、単に改行文字(newline character)が含まれることを指すのか、それとも複数の論理行にまたがることを指すのか、といった解釈の余地がありました。
Go言語の設計者の一人であるRobert Griesemer氏(コミットの著者)は、この曖昧さを解消し、仕様の厳密性を高めるために、より明確な「改行 (newline)」という用語に統一する必要があると判断しました。Go言語の字句規則において、改行は特定の意味を持つ重要な要素であり、その存在がトークンの区切りやコメントの終了を決定します。したがって、「複数行」という非形式的な表現を避け、「改行」という明確に定義された字句要素を用いることで、仕様の解釈のブレを防ぎ、実装の一貫性を保証することが変更の背景にあります。
前提知識の解説
プログラミング言語の仕様書
プログラミング言語の仕様書は、その言語の構文、意味、およびセマンティクスを形式的に記述した文書です。これは、言語のコンパイラ、インタプリタ、リンタ、デバッガなどのツールを開発する際の唯一の「真実の源」となります。仕様書は、曖昧さを排除し、異なる実装間での互換性を保証するために、非常に厳密かつ詳細に記述される必要があります。
字句解析 (Lexical Analysis) とトークン (Token)
字句解析は、コンパイラの最初のフェーズであり、ソースコードを「トークン」と呼ばれる意味のある最小単位の並びに変換します。トークンには、キーワード(if
, for
)、識別子(変数名、関数名)、演算子(+
, -
)、リテラル(数値、文字列)、区切り文字(;
, {
)などがあります。
改行 (Newline) と空白 (Whitespace)
プログラミング言語において、改行文字(\n
、\r\n
など)は、通常、空白文字(スペース、タブなど)の一種として扱われますが、多くの言語では特別な意味を持ちます。Go言語では、改行はセミコロン挿入規則(automatic semicolon insertion)に影響を与えたり、行コメントの終了を意味したりするなど、構文的に重要な役割を果たすことがあります。
Go言語のコメント
Go言語には2種類のコメントがあります。
- 行コメント (Line comments):
//
で始まり、行末まで続きます。 - 一般コメント (General comments):
/*
で始まり、*/
で終わります。複数行にわたることができます。
Go言語の仕様では、これらのコメントが字句解析においてどのように扱われるかが定義されています。特に、コメントが「改行のように振る舞う」という記述は、そのコメントが存在する場所に改行があるかのように、トークンの区切りやセミコロン挿入に影響を与えることを意味します。
Go言語の文字列リテラル
Go言語には2種類の文字列リテラルがあります。
- 生文字列リテラル (Raw string literals): バッククォート
`
で囲まれます。エスケープシーケンスは解釈されず、改行を含むことができます。 - 解釈済み文字列リテラル (Interpreted string literals): ダブルクォート
"
で囲まれます。バックスラッシュによるエスケープシーケンスが解釈され、通常は改行を含むことができません(ただし、エスケープシーケンスによる改行は可能です)。
技術的詳細
このコミットの技術的詳細は、Go言語仕様書における「曖昧な表現の排除」と「厳密な用語の適用」に集約されます。
「複数行にわたる」の曖昧さ
「複数行にわたる」という表現は、以下のような解釈の余地がありました。
- 物理的な複数行: ソースコードエディタ上で、視覚的に複数行に表示されること。
- 論理的な複数行: 構文解析器が認識する論理的な行の区切り(通常は改行文字によって定義される)が複数存在すること。
- 改行文字の存在: 単に1つ以上の改行文字が含まれていること。
Go言語の仕様では、字句解析の段階で改行文字がどのように扱われるかが重要です。例えば、行コメントは改行で終了し、一般コメントは改行を含むことで特定の振る舞いをします。文字列リテラルも、改行を含むか否かでその種類や解釈が変わります。
「改行」への統一の重要性
「改行 (newline)」は、Go言語の字句規則において明確に定義された文字(または文字シーケンス)です。仕様書でこの用語を使用することで、以下の利点があります。
- 厳密性: 「改行」は単一の明確な概念を指し、解釈の余地がありません。これにより、仕様の曖昧さが排除されます。
- 実装の一貫性: コンパイラやツール開発者は、「改行」という明確な定義に基づいて実装を行うことができ、異なる実装間での挙動の不一致を防ぎます。
- 形式的定義との整合性: プログラミング言語の仕様は、形式言語理論に基づいた厳密な定義と整合性が取れているべきです。「複数行」のような非形式的な表現は、この整合性を損なう可能性があります。
具体的な変更点
コミットでは、以下の3箇所で表現が修正されています。
-
一般コメントの振る舞い:
- 変更前:
A general comment that spans multiple lines acts like a newline, otherwise it acts like a space.
- 変更後:
A general comment containing one or more newlines acts like a newline, otherwise it acts like a space.
- 解説: 一般コメントが「改行のように振る舞う」条件を、「複数行にわたる」から「1つ以上の改行を含む」に明確化しました。これにより、コメントの内部に改行文字が存在するかどうかが、そのコメントが改行として扱われるかどうかの基準となることが明確になります。
- 変更前:
-
生文字列リテラル:
- 変更前:
in particular, backslashes have no special meaning and the string may span multiple lines.
- 変更後:
in particular, backslashes have no special meaning and the string may contain newlines.
- 解説: 生文字列リテラルが「複数行にわたる」ことができるという記述を、「改行を含むことができる」に修正しました。これは、生文字列リテラルが文字通り改行文字をその値として保持できることをより正確に表現しています。
- 変更前:
-
解釈済み文字列リテラル:
- 変更前:
The text between the quotes, which may not span multiple lines, forms the value of the literal, with backslash escapes interpreted as they are in character literals
- 変更後:
The text between the quotes, which may not contain newlines, forms the value of the literal, with backslash escapes interpreted as they are in character literals
- 解説: 解釈済み文字列リテラルが「複数行にわたることができない」という記述を、「改行を含むことができない」に修正しました。これは、解釈済み文字列リテラルが、エスケープされていない改行文字を直接その値として持つことができないという制約をより正確に示しています。
- 変更前:
これらの変更は、Go言語の字句規則と構文規則の基盤となる概念をより厳密に定義し、仕様書全体の整合性と正確性を高める上で非常に重要です。
コアとなるコードの変更箇所
変更は doc/go_spec.html
ファイル内で行われています。
--- a/doc/go_spec.html
+++ b/doc/go_spec.html
@@ -1,5 +1,5 @@
<!-- title The Go Programming Language Specification -->
-<!-- subtitle Version of December 14, 2011 -->
+<!-- subtitle Version of December 15, 2011 -->
<!--
TODO
@@ -146,7 +146,7 @@ and stop at the end of the line. A line comment acts like a newline.
<li>
<i>General comments</i> start with the character sequence <code>/*</code>
and continue through the character sequence <code>*/</code>. A general
-comment that spans multiple lines acts like a newline, otherwise it acts
+comment containing one or more newlines acts like a newline, otherwise it acts
like a space.
</li>
</ol>
@@ -453,14 +453,14 @@ Raw string literals are character sequences between back quotes
back quote. The value of a raw string literal is the
string composed of the uninterpreted characters between the quotes;
in particular, backslashes have no special meaning and the string may
-span multiple lines.\n+contain newlines.
Carriage returns inside raw string literals
are discarded from the raw string value.
</p>
<p>
Interpreted string literals are character sequences between double
quotes <code>""</code>. The text between the quotes,\n-which may not span multiple lines, forms the
+which may not contain newlines, forms the
value of the literal, with backslash escapes interpreted as they\n are in character literals (except that <code>\\\'</code> is illegal and\n <code>\\\"</code> is legal). The three-digit octal (<code>\\</code><i>nnn</i>)\n
コアとなるコードの解説
上記の差分は、HTMLコメントの更新と、Go言語仕様の本文における3つの重要な変更を示しています。
-
HTMLコメントの更新:
-<!-- subtitle Version of December 14, 2011 --> +<!-- subtitle Version of December 15, 2011 -->
これは、仕様書のバージョン日付をコミット日に合わせて更新したものです。これは機能的な変更ではなく、文書のメタデータに関する更新です。
-
一般コメントの定義の変更:
-comment that spans multiple lines acts like a newline, otherwise it acts +comment containing one or more newlines acts like a newline, otherwise it acts
この変更は、一般コメント(
/* ... */
)が「改行のように振る舞う」条件を修正しています。以前は「複数行にわたる (spans multiple lines)」と記述されていましたが、これは曖;昧でした。新しい記述「1つ以上の改行を含む (containing one or more newlines)」は、コメントのテキスト内に実際に改行文字が存在する場合にのみ、そのコメントが字句解析において改行として扱われることを明確にしています。これにより、コンパイラがコメントを処理する際の挙動がより厳密に定義されます。 -
生文字列リテラルの定義の変更:
-span multiple lines. +contain newlines.
生文字列リテラル(バッククォートで囲まれた文字列)に関する記述です。以前は「複数行にわたることができる (may span multiple lines)」とされていましたが、これは「改行を含むことができる (may contain newlines)」に修正されました。生文字列リテラルは、その内部の文字をそのまま解釈するため、改行文字もそのまま文字列の値の一部として扱われます。この変更は、その特性をより正確に表現しています。
-
解釈済み文字列リテラルの定義の変更:
-which may not span multiple lines, forms the +which may not contain newlines, forms the
解釈済み文字列リテラル(ダブルクォートで囲まれた文字列)に関する記述です。以前は「複数行にわたることができない (may not span multiple lines)」とされていましたが、これは「改行を含むことができない (may not contain newlines)」に修正されました。解釈済み文字列リテラルは、通常、エスケープされていない改行文字を直接含むことはできません(改行を表現するには
\n
などのエスケープシーケンスを使用します)。この変更は、この制約をより正確かつ厳密に記述しています。
これらの変更は、Go言語の字句規則における「改行」の役割と、それがコメントや文字列リテラルの解釈にどのように影響するかを、より明確かつ厳密に定義することを目的としています。これにより、Go言語の仕様書全体の正確性と一貫性が向上し、異なるGoコンパイラやツールの実装間での互換性が保証されます。
関連リンク
- Go言語公式ウェブサイト: https://golang.org/
- Go言語仕様書: https://golang.org/ref/spec (このコミットが修正した文書の最新版)
- Go言語のコードレビューシステム (Gerrit): https://go-review.googlesource.com/
- コミットメッセージに記載されているCL (Change-list) リンク:
https://golang.org/cl/5490046
(現在はhttps://go-review.googlesource.com/c/go/+/5490046
にリダイレクトされます)
- コミットメッセージに記載されているCL (Change-list) リンク:
参考にした情報源リンク
- Go言語仕様書 (コミット対象の文書): https://golang.org/ref/spec
- Go言語の字句要素に関する公式ドキュメントやチュートリアル (一般的な情報源として)
- プログラミング言語の設計とコンパイラに関する一般的な知識
- Gitのコミット履歴と差分表示の解釈
- GitHubのコミットページ
- Robert Griesemer氏のGo言語における役割に関する情報 (Go言語の設計者の一人)
- Go言語のコメントと文字列リテラルに関する公式ドキュメントやブログ記事 (変更内容の背景理解のため)