第2章でALGOL 60が「ブロック構造」という文法的遺産を残したことを見ました。本章では、その遺産が引き金となって 1960年代後半に起きた、プログラミング史上もっとも有名な思想革命——構造化プログラミングと、 それをめぐる「GOTO論争」を扱います。これは単なる文法の話ではなく、「正しいプログラムとは何か」という プログラミングの哲学そのものをめぐる戦いでした。

スパゲッティコードの時代

初期の言語、たとえば行番号付きBASICや初期のFORTRANでは、制御の流れを GOTO 文で操りました。 「GOTO 100」と書けば、プログラムは行番号100へ無条件にジャンプします。一見シンプルですが、これが曲者でした。

10 LET I = 1
20 IF I > 5 THEN GOTO 60
30 PRINT I
40 LET I = I + 1
50 GOTO 20
60 PRINT "DONE"

上の例はまだ素直ですが、規模が大きくなると GOTO があちこちへ飛び交い、実行の流れが追えなくなります。 プログラムのどこからどこへ制御が移るのか、人間の頭では把握しきれない——これが悪名高い 「スパゲッティコード」です。麺が複雑に絡み合うように、コードの制御フローが絡まってしまうのです。 バグの温床であり、保守は悪夢でした。

構造化定理 — 3つの構造で十分という証明

突破口は理論から開かれました。1966年、コラド・ベームとジュゼッペ・ヤコピーニが 「構造化定理(structured program theorem)」を証明します。その主張は驚くほど力強いものでした—— あらゆる計算可能な処理は、たった3つの制御構造の組み合わせだけで表現できる

制御構造 意味 現代の構文例
逐次(sequence) 文を上から順に実行する 文を並べて書く
選択(selection) 条件によって分岐する if / else / switch
反復(iteration) 条件を満たす間くり返す while / for

つまり、GOTO で任意の場所へ飛ばなくても、この3つさえあれば何でも書ける——理論がそう保証したのです。 これは構造化プログラミング運動に、決定的な「理論的正当性」を与えました。あとは、実践がそれに続くだけでした。

Dijkstra の一撃 — 「Go To Considered Harmful」

実践の号砲を鳴らしたのが、エドガー・ダイクストラ(Edsger W. Dijkstra)です。 1968年3月、計算機科学のトップ誌 Communications of the ACM に、彼の短い寄稿が掲載されます。 タイトルは 「Go To Statement Considered Harmful(go to文は有害と考えられる)」

ダイクストラの論点は明快でした。GOTO はプログラムの任意の地点へ飛べるため、 「いまプログラムがどういう状態にあるか」を人間が把握する手がかりを破壊してしまう。 対して、選択(if)や反復(while)による構造化された制御は、コードの静的なテキスト上の位置実行時の進行状況を対応づけられる。だから GOTO は可能な限り排除すべきだ、と。

Knuth の反論 — 全廃は行き過ぎだ

しかし、革命には必ず揺り戻しがあります。1974年、アルゴリズム研究の巨人ドナルド・クヌース(Donald Knuth)が 「Structured Programming with go to Statements(go to文を用いた構造化プログラミング)」という論文を発表しました。

クヌースは構造化プログラミングの中核思想——コードを明快に構成すべきという理念——は全面的に支持しました。 しかし、GOTO完全廃止には反対します。ループの途中から脱出する場合など、 むしろ GOTO を使ったほうが明快で効率的なケースが現実には存在する、と具体例を挙げて示したのです。 彼の立場は「教条主義に陥らず、可読性と効率のバランスで判断せよ」という、きわめて実務的なものでした。

graph LR
  A[ALGOL 60\nブロック構造]
  T[構造化定理\n1966 Böhm-Jacopini]
  D[Dijkstra\n1968 GOTO有害]
  K[Knuth\n1974 反論・バランス論]
  P[Pascal\n1970 教育的明快さ]
  C[C\n1972 実用と効率]
  STD[構造化=常識へ\n20世紀末]
  A --> T
  T --> D
  D --> K
  D --> P
  A --> C
  K --> STD
  P --> STD
  C --> STD
  style D fill:#f97316,stroke:#ea580c,color:#fff
  style K fill:#8b5cf6,stroke:#6d28d9,color:#fff
  style STD fill:#14b8a6,stroke:#0d9488,color:#fff
ALGOLのブロック構造から構造化定理・Dijkstra・Knuthの論争を経て、PascalとCに結実。20世紀末には構造化は「常識」になった

理念の結実 — Pascal と C

構造化プログラミングの理念は、1970年代初頭に登場した2つの言語に、対照的な形で結実しました。

Pascal(1970)— 教育のための規律

GOTO論文のタイトルを付けたニクラウス・ヴィルトは、1970年Pascal を設計します。 目的は教育でした。構造化プログラミングの規律を、学生が自然に身につけられるよう、 begin / end による明快なブロック、強い型付け、見通しのよい文法を備えました。

program Average;
var
  i, sum: Integer;
  nums: array[1..3] of Integer = (10, 20, 30);
begin
  sum := 0;
  for i := 1 to 3 do        { 反復: 構造化されたループ }
    sum := sum + nums[i];
  writeln('平均 = ', sum div 3);
end.

C(1972)— 実用と効率の構造化

一方、ベル研究所のデニス・リッチーが 1972年に開発した C は、まったく違う動機から生まれました。 UNIXというOSを記述するための、実用的なシステム言語です。Cも構造化制御(if/while/for)を全面採用しましたが、 その哲学は「プログラマを信頼する(Trust the programmer)」。危険なポインタ操作も低レベルなメモリアクセスも、 必要なら止めない。構造化の恩恵を受けつつ、効率と自由を最大化する設計でした。

#include <stdio.h>

int main(void) {
    int nums[3] = {10, 20, 30};
    int sum = 0;
    for (int i = 0; i < 3; i++)   /* 反復: Cの中括弧ブロック */
        sum += nums[i];
    printf("平均 = %d
", sum / 3);
    return 0;
}

同じ「構造化」という理念が、Pascalでは教育的明快さとして、Cでは実用的効率として 結晶化したことは興味深い対比です。そしてこの2つの設計思想の違い——「安全と規律」か「自由と信頼」か——は、 以降の言語設計を貫く永遠のテーマになっていきます。Cはその後、UNIXの普及とともに世界を席巻し、 C++・Java・JavaScript・Go・Rust など、無数の言語に「中括弧の文法」と思想を残しました(第6章の系統樹で詳述)。

理解度チェック

問題 0 / 50%
Q1

1966年の「構造化定理(Böhm-Jacopini)」が証明したことは何ですか?

キーボード: 1〜4 で選択、Enter で回答