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

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

このコミットは、Go言語の初期段階におけるprintの構文変更、具体的にはprintがステートメントから組み込み関数へと移行する過程で、既存のコードベース内の古いスタイルのprint呼び出しを修正したものです。src/lib/fmt/format.goファイル内のコメント行の例が更新されています。

コミット

fix old-style print call in constant

R=rsc OCL=26093 CL=26093

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

https://github.com/golang/go/commit/5559ff6ece381c8ee1b27779708bc821f609eafb

元コミット内容

fix old-style print call in constant
    
R=rsc
OCL=26093
CL=26093

変更の背景

このコミットは、Go言語の初期開発段階における重要な言語仕様の変更、特にprintおよびprintlnが組み込みのステートメント(キーワードのように振る舞う)から、通常の組み込み関数へと移行したことに関連しています。

Go言語の初期バージョンでは、printprintlnは特殊なステートメントとして扱われていました。これは、C言語のprintfのような関数とは異なり、引数を括弧で囲む必要がないなど、通常の関数呼び出しとは異なる構文を持っていました。しかし、言語の設計が進むにつれて、このような特殊なステートメントは言語の統一性を損ない、パーサーの実装を複雑にするという問題が浮上しました。

そのため、Go言語の設計者たちは、printprintlnを通常の関数呼び出し構文(引数を括弧で囲む)に統一することを決定しました。この変更により、言語の構文がより一貫性のあるものになり、コンパイラの処理も簡素化されました。

このコミットは、その構文変更に伴い、Goの標準ライブラリであるfmtパッケージ内のformat.goファイルにあるコメント内の古いprintステートメントの例を、新しい関数呼び出し構文に修正するものです。これは、言語仕様の変更がコードベース全体に波及し、既存のコードやドキュメント、例もそれに合わせて更新する必要があったことを示しています。

前提知識の解説

Go言語の初期開発

Go言語は、GoogleでRob Pike、Ken Thompson、Robert Griesemerによって設計され、2009年にオープンソースとして公開されました。このコミットが行われた2009年3月は、Go言語がまだ活発に開発され、言語仕様が固まりつつある非常に初期の段階でした。この時期には、現在では当たり前となっているGoの構文やセマンティクスが頻繁に変更されていました。

printprintlnの歴史

Go言語には、デバッグや簡単な出力のためにprintprintlnという組み込み関数(または初期にはステートメント)が存在します。これらはfmtパッケージのfmt.Printfmt.Printlnとは異なり、インポートなしで利用できます。しかし、これらは主にデバッグ用途であり、本番コードでの使用は推奨されません(通常はfmtパッケージを使用します)。

このコミットの時点では、printは以下のような構文で使われていました(古いスタイル): print expression 例: print "Hello, World!"

変更後(新しいスタイル): print(expression) 例: print("Hello, World!")

この変更は、Go言語の構文解析器の簡素化と、言語全体の一貫性を高めるためのものでした。

fmtパッケージ

fmtパッケージは、Go言語におけるフォーマットされたI/O(入出力)を実装するための標準ライブラリです。C言語のprintfscanfに似た機能を提供し、文字列、数値、構造体などの様々なデータ型を整形して出力したり、入力から解析したりすることができます。

このコミットで変更されたsrc/lib/fmt/format.goは、fmtパッケージの内部実装の一部であり、特にフォーマット処理のコアロジックや、その使用例が記述されているファイルと考えられます。

技術的詳細

このコミットの技術的詳細は、Go言語のパーサーとコンパイラの設計、そして言語の進化における構文の安定化に焦点を当てています。

  1. 構文解析の簡素化:

    • printがステートメントであった場合、コンパイラはprintキーワードの後に続くトークンが式であると特別に認識し、その式を評価して出力するという特殊なルールを適用する必要がありました。これは、言語の文法規則(BNFなど)に特別なプロダクションを追加することを意味します。
    • printが関数になった場合、コンパイラはprintを通常の関数名として扱い、その後に続く括弧内の引数を評価して関数に渡すという、一般的な関数呼び出しのルールを適用できます。これにより、パーサーのロジックが簡素化され、言語の文法がより規則的になります。
  2. 言語の一貫性:

    • Go言語は、シンプルさと一貫性を重視する設計思想を持っています。printが特殊なステートメントであることは、他のすべての関数が括弧を使って呼び出されるという一般的なルールからの逸脱でした。この不一致は、学習コストを増やし、コードの可読性を低下させる可能性がありました。
    • printを関数にすることで、Go言語内のすべての「アクション」が関数呼び出しという統一されたメカニズムを通じて行われるようになり、言語全体の一貫性が向上しました。
  3. 後方互換性への配慮:

    • このような言語仕様の変更は、既存のコードベースに大きな影響を与えます。Go言語の開発チームは、初期段階でこのような変更を積極的に行い、言語が広く採用される前に安定した構文を確立しようとしました。このコミットは、その過程で発生した、既存のコード(この場合はコメント内の例)を新しい構文に適合させるための典型的な作業です。
  4. fmtパッケージの例:

    • 変更された行は、fmtパッケージのformat.goファイル内のコメントブロックにあります。このコメントは、fmtパッケージのFmt型(おそらくフォーマッタのインスタンス)の使用方法を示す例です。
    • f.Fmt_d(1234).Fmt_s("\n").Str()は、Fmtインスタンスのメソッドチェーンを使って数値をフォーマットし、改行を追加し、最終的に文字列として取得する操作を示しています。この結果の文字列をprintで出力するという例でした。
    • この例が更新されたのは、単に古い構文の例を新しい構文に合わせるためであり、fmtパッケージ自体の機能が変更されたわけではありません。

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

変更はsrc/lib/fmt/format.goファイルの一箇所のみです。

--- a/src/lib/fmt/format.go
+++ b/src/lib/fmt/format.go
@@ -34,7 +34,7 @@ func init() {
 methods return ``self'' so the operations can be chained.
 
 f := fmt.New();
-print f.Fmt_d(1234).Fmt_s("\n").Str();  // create string, print it
+print(f.Fmt_d(1234).Fmt_s("\n").Str());  // create string, print it
 f.Fmt_d(-1234).Fmt_s("\n").Put();  // print string
 f.Fmt_ud(1<<63).Putnl();  // print string with automatic newline
 */

具体的には、36行目のprint呼び出しが変更されています。

コアとなるコードの解説

変更された行は、src/lib/fmt/format.goファイル内のコメントブロックの一部です。このコメントブロックは、fmtパッケージのFmt型(おそらくフォーマット操作を行うための内部的な型)の使用方法を示すコード例を含んでいます。

元の行: print f.Fmt_d(1234).Fmt_s("\n").Str(); // create string, print it

変更後の行: print(f.Fmt_d(1234).Fmt_s("\n").Str()); // create string, print it

この変更は、printステートメントがprint関数に変わったことに対応するものです。

  • f := fmt.New();: fmtパッケージから新しいフォーマッタインスタンスを作成しています。
  • f.Fmt_d(1234): FmtインスタンスのFmt_dメソッドを呼び出し、整数1234をフォーマットしています。Fmt_dはおそらく"format decimal"(10進数をフォーマット)を意味します。
  • .Fmt_s("\n"): チェーンされた呼び出しで、Fmt_sメソッドを使って改行文字列"\n"を追加しています。Fmt_sはおそらく"format string"(文字列をフォーマット)を意味します。
  • .Str(): フォーマットされた結果を文字列として取得しています。
  • print(...): 取得した文字列を標準出力に出力しています。

この行は、fmtパッケージの内部的なフォーマット機能がどのように連鎖的に使用され、最終的に文字列として取得されるかを示す例であり、その結果をprintで出力するというデモンストレーションです。このコミットは、このデモンストレーションのprint構文を、当時のGo言語の最新の仕様に合わせるために行われました。これは機能的な変更ではなく、構文的な修正であり、コードの動作には影響を与えません。

関連リンク

参考にした情報源リンク

  • Go言語の公式リポジトリのコミット履歴: https://github.com/golang/go
  • Go言語の初期の設計に関する議論やメーリングリストのアーカイブ(Go言語のprintステートメントから関数への変更に関する詳細な議論が見つかる可能性があります)
  • Go言語の歴史に関する記事やブログポスト(非公式なものも含む)
    • 例: "A brief history of Go" by Russ Cox (Go言語の歴史に関する公式ブログ記事など)
    • Go言語の初期の変更に関する情報源は、当時のメーリングリストの議論や、Go言語の設計に関する論文やブログ記事に散見されます。