制御構造

**制御構造**（せいぎょこうぞう）は、プログラミング言語においてプログラム中の命令や文の実行順序を制御する言語構成要素である。プログラムの制御フローを記述する基本要素として、条件分岐、反復、手続き呼出しなどの場面で用いられる。

## 概要

機械語において制御構造に相当するのは分岐命令であり、通常は連続的に増加するプログラムカウンタの値を変更することで実現される。ほとんどのプロセッサは条件分岐および無条件分岐を備えており、サブルーチン呼出しを支援する命令を持つものも多い。高水準言語における選択・反復などの制御構造は、コンパイラによって分岐命令などの組合せに変換されて実装される。

## 原始的な機能
### ラベル

ラベルとは、コード中の固定の位置を示す何らかのシンボルであり、gotoの飛び先や、breakで抜ける対象として参照される。GCC拡張では、void * ポインタの値として扱うこともできる（Labels as Values）。

一部の言語（FORTRANやBASIC）では行番号がラベルの一種として使われる。例えば BASIC では次のようになっている（`10`や`20`が行番号でありラベルでもある）。


```qbasic
10 LET X = 3
20 PRINT X
```


CやAdaといった言語のラベルは識別子であり、文の前に書かれ、その直後にコロンが書かれる。例えば C では次のようになる。


```c
Success: printf ("The operation was successful.\n");
```


Algol 60はラベルとして識別子も非負整数も使用可能（どちらもその後にコロンが続く）だが、多くのALGOL系言語では非負整数をラベルとして許容していない。

### goto

goto文は最も典型的な無条件のジャンプである。キーワードとしては大文字だったり小文字だったり空白が入って`go to`だったり、単に`go`だったりするが、その構文はだいたいのものが以下のようになっている。

 **goto** *label*

goto文の実行により、次に実行される文は、ラベルの付いた文となる。

### サブルーチン

サブルーチンには、手続き、ルーチン、プロシージャ、関数（特に値を返す場合）、メソッド（特に何らかのクラスに属する場合）など様々な名称がある。

1950年代、コンピュータのメモリは非常に小さかったため、サブルーチンの第一の目的はプログラムのサイズを削減することにあった。サブルーチンとして書かれたコードをプログラム内のあちこちから使用することでプログラム全体のコードサイズを削減したのである。現在ではサブルーチンはプログラムを構造化するために使われる。すなわち、特定のアルゴリズムを分離したり、特定のデータにアクセスするメソッドを隠蔽したりする。多数のプログラマが共同でプログラム開発をする場合、サブルーチンはある種のモジュール性を提供し、仕事の分割点の役割も果たす。

サブルーチンに引数があればさらに便利になる。例えば、多くのプログラミング言語に組み込まれた平方根を求めるサブルーチンは、引数として平方根を求めたい数を与えることができる。

プログラミング言語によっては再帰呼び出しが可能である。つまり、サブルーチンが直接的あるいは間接的に自分自身を呼び出すことができる。クイックソートや木構造を探索するアルゴリズムなどは再帰を使った方が素直に表現できる。

サブルーチンを使用すると、引数の受け渡し、サブルーチン呼び出し、コールスタック処理、サブルーチンからの復帰などのオーバヘッドによりプログラム性能が若干低下する。実際のオーバヘッドはハードウェアおよびソフトウェアのアーキテクチャに依存する。コンパイラによってはインライン展開を効果的に使用してオーバヘッドの低減を図るものもある。

サブルーチンからの復帰は、サブルーチンの最後尾に到達しないと復帰できないプログラミング言語もあれば、**return** 文や **exit** 文を用いていつでも復帰できるプログラミング言語もある。これは最後尾への分岐と等価であり、制御構造を複雑化するものではない。必要に応じて複数のそれらの文をサブルーチン内に置くことができる。

## 必要最小限の構造化制御フロー

1966年、Böhm と Jacopini は Communications of the ACM 誌で論文を発表し、**goto** を使って書かれたプログラムが選択 (IF THEN ELSE) とループ (WHILE condition DO xxx) のみを使って goto を使わずに書き換えられることを示した（コードの一部を複製したり、真理値変数を追加する必要がある）。後に彼らは選択もループと追加の真理値変数で置き換え可能であることを示した（**構造化定理**）。

ただし、そのような書き換えが可能という事実は、単に「機械語で書けば何でも書ける」という程度の意味で、必ずしもそれが望ましいということを意味しない。実際、理論的にはコンピュータは一種類の命令のみ（OISC）で何でもできる（チューリング完全）が実用的ではなく、実際のコンピュータは多数の命令を備えている。

また他の研究により、入口と出口をそれぞれ一つずつ持つ制御構造が、そうでない構造よりも理解し易いということが示された。特に、そのような制御構造は、プログラムの任意の箇所に制御構造を乱すことなく挿入可能な点が有利とされた。入口と出口がそれぞれ一つのみなら、資源の確保と解放などを対となるように書けば、かならず対になるように実行される。この利点があるため、コーディング規則でもそのように定められる場合がある。

しかし、goto文を無くしたプログラムが理解し易いものかには議論の余地があり、goto文有りでは簡潔なコードが書き換えることで煩雑になることもあり、「理解し易い」かどうかはプログラマなどの主観によることになる。

## 構造化された制御要素

制御構造の表し方はプログラミング言語により様々で、構造を開始するキーワードと終了するキーワードを組み合わせるもの、開始するキーワードのみでブロックなどは他の構文（構造）に任せるもの、空白や改行などで暗黙的に表すものなどがある。

; 主に開始/終了キーワードを使う言語
: 終了キーワードはいくつかの種類がある。
:* Ada、Fortran 90: **キーワード**で開始し**end キーワード**で終了する。例えば、`if ... end if`、`loop ... end loop`。
:* Algol 68: **キーワード**で開始し逆に綴り終了する。例えば、`if ... fi`、`case ... esac`。
:* Fortran 77: **キーワード**で開始し**endキーワード**で終了する。例えば、`IF ... ENDIF`、`DO ... ENDDO`。
:* Modula-2: **キーワード**で開始し**END**で終了する。
:* Visual Basic: 制御構造ごとに固有の終了キーワードがある。例えば、`If ... End If`、`For ... Next`、`Do ... Loop`、`While ... Wend`。

; 主に開始キーワードのみを使う言語/暗黙的な言語など
: この種の言語は文の並びをひとまとめ（ブロック）にする何らかの方法を持っている。
:* Algol 60、Pascal: 開始/終了キーワードを使ったブロック。例えば、`begin ... end`。
:* PL/I: 開始/終了キーワードを使ったブロック。例えば、`DO ... END`。
:* C、C++、Java、Perl、PHP、PowerShell: 中括弧を使ったブロック。例えば、`{ ... }`。
:* Python: インデントによる暗黙的なブロック。オフサイドルール参照。
:* Haskell: インデントによる暗黙的なブロック、およびの中括弧を使ったブロックを自由に混合可能。

## 選択
### if-then-(else)

条件式と条件付き実行は、条件節（たいていは式）の評価結果の真偽によって異なる式やブロックを選択し実行する。

; `IF..GOTO`
: 非構造化言語に見られる形式で、典型的な機械語命令をそのまま言語に持ってきたものである。条件が真なら指定されたラベル（または行番号）へジャンプ (GOTO) する。
; `IF..THEN..(ENDIF)`
: ジャンプに限らず、単純な文や入れ子になったブロックを THEN というキーワードの後に置くことができる。構造化された形式である。
; `IF..THEN..ELSE..(ENDIF)`
: 上と同じだが、条件が偽の場合の動作も記述できる。これが最も一般的な形式で、様々なバリエーションがある。終了キーワード `ENDIF` が必要な場合とそうでない場合がある。C言語やそこからの派生言語では終了キーワードは不要で、'then' に相当するキーワードも不要なことが多いが、その場合は条件式を括弧で囲む必要がある。

#### elseif
文法の設計によっては、
 IF 条件 THEN
   ...
 ELSE
   IF 条件 THEN
     ...
   ELSE
     IF 条件 THEN
       ...
     FI
   FI
 FI
のように、どんどんネストが深くなるような書き方をせざるをえない場合がある。これは ELSEIF のようなキーワードの導入で解決できる。実際に使われるキーワードは`elseif`、`elsif`、`elif`など言語による差異が多い。言語によっては`else if`という「2語から成るキーワードのようなもの」という設計のものもある。

あまり一般的でないバリエーションとして、以下のような例がある。
* FORTRANなどの一部の言語では、3方向の分岐を扱う「算術IF文」があり、数値を正か、ゼロか、負か判定して処理を分岐させる。
* 多くの関数型言語などでは`if文`が関数や式として実装されており、そのようなifは評価した式の結果を返す。
* 一部の言語では`if文`が演算子の様に実装されており、例えばC言語の条件演算子がある。
* PerlではC言語風の `if` だけでなく、`when` と `unless` や、コードの後に条件式が来る `if` がある。
* Smalltalkでは言語組込みの機能としてではなく、`ifTrue` と `ifFalse` というメッセージに手続き引数を与えることで、条件付き実行ができる。
関数の引数を積極評価してしまう言語では、条件実行のようなものを関数にできない。遅延評価のような機構が何かあれば、条件実行を特に言語機能にしなくても、引数を遅延評価する関数によって、条件実行もできる。

### パターンマッチング

ここではOCamlの例を挙げる。

 **match** fruit **with**
 **|** "apple" ***' cook pie
 '''|''' "coconut" ***' cook dango_mochi
 **|** "banana" **** mix**;;**

### switchとcase

switch文（言語によっては「case文」）は、指定された値を指定された定数群と比較し、最初に一致した定数に従ってその後の処理を決定するものである。一般にどの定数とも一致しなかった場合を想定したデフォルト動作を 'else' や 'otherwise' などとして用意しておく。ルックアップテーブルなどを使ったコンパイラ最適化が可能である。動的プログラミング言語では比較対象が定数式である必要はなく、パターンマッチに拡張することが可能である。例えば下記のシェルスクリプトの例で `'*)'` は任意の文字列にマッチングする正規表現を使ってデフォルト動作を指定している。SQLの `decode` のように、関数のような見た目のものもある。

## ループ

ループはソースコード上で1回だけ書かれた文の並びを連続して複数回実行することである。ループの「中」のコード（本体と呼び、下記の例では *xxx* で表されている）は指定回数実行されるか、指定されたコレクションの各要素に対応して実行されるか、何らかの条件が成立するまで繰り返し実行される。無限に繰り返されることもある。

SchemeやHaskellのような関数型言語では、ループよりも再帰呼び出しや不動点コンビネータを使用して実現されることが多い。
末尾再帰は再帰呼び出しの特殊ケースであり、容易にループに変換できる。

### カウント制御ループ

指定された回数だけブロックを繰り返すループである。以下の例で N が 1 より小さい場合、ループ本体は全く実行されない。カウントは多くの場合増える方向だけでなく減る方向にも設定可能で、1回に増える量も 1 以外に設定できることが多い。

 FOR I = 1 TO N            **for** I := 1 **to** N **do** **begin**
     xxx                       xxx
 NEXT I                    **end**;
 
 DO I = 1,N                **for** ( I=1; IN; ++I ) {
     xxx                       xxx
 END DO                    }

多くのプログラミング言語では小数の実装として浮動小数点数を使う。ところが、浮動小数点数はハードウェアの制限により精度に限界があるため、ループの繰り返し回数がハードウェアやコンパイラによって変わる場合がある。例えば、以下のようなループでは、繰り返し回数が9回か10回かそれ以外かはっきりと定まらない（定まるように言語側で細かく定義されていることはある）：
 **for** X := 0.1 **step** 0.1 **to** 1.0 **do**
さらに言えば、Xに繰り返し加算すると丸め誤差が累積していき、想定した数列である 0.1, 0.2, 0.3, ..., 1.0 からかけ離れていくことがありうる。
このため、多くのカウント制御ループでは整数のみが使われる。

### 条件制御ループ

条件（条件式）が指定されており、その式を評価した結果が真であれば（あるいは、偽であれば）ループを繰り返す。条件のテストがループの先頭にある場合と最後にある場合がある。前者の場合、ループ本体を全く実行しないことがありうるが、後者の場合は、繰り返しの判定を実行後に行うため、少なくとも1回はループ本体を実行する。

 DO WHILE (test)           **repeat** 
     xxx                       xxx 
 END DO                    **until** test;
 
 **while** (test) {            **do**
     xxx                       xxx
 }                         **while** (test);

は通常のループ内で値の変化を検出する手段として使われ、値のグループの処理のトリガーとなる。ループ内で変化する値（群）をキーで監視し、可変な値に関連したグループイベント処理へとプログラムのフローを変換する。

 DO UNTIL (End-of-File)
    IF new-zipcode  current-zipcode
       display_tally(current-zipcode, zipcount)
       
       current-zipcode = new-zipcode
       zipcount = 0
    ENDIF
    
    zipcount++
 LOOP

### コレクション制御ループ

明示的に配列や集合やコレクションの全要素に対応してループを回すことができる。

 someCollection **do**: [:eachElement |xxx].
    
 **for** Item **in** Collection **do** **begin** xxx **end**;
 
 **foreach** (item; myCollection) { xxx }
 
 **foreach** someArray { xxx }
 
 **foreach** (someArray as $k  $v) { xxx }
 
 Collection coll; **for** (String s : coll) {}
 
 **foreach** (**string** s **in** myStringCollection) { xxx }
 
 $someCollection | ForEach-Object { $_ }
    
 **forall** ( index = first:last:step... )

### 汎用の繰り返し
C言語の **for** 文や Common Lisp の **do** のような汎用性の高い繰り返し要素を使えば、前述の各種ループもその他のループも実現できる。例えば、複数のコレクションを並列に回したりできる。もっとも、個別のループ構造がある場合、そちらを使った方がコードの目的をより明確に表現できる。

### 無限ループ
場合によっては無限にループする方がプログラムに適していることもあるし、何らかのエラーが発生するまでループするという場合もある。実際、イベント駆動型プログラム（サーバなど）はイベント制御ループを永遠に回り続け、プロセスが操作者によって終了させられたときだけループを停止する。

ただし一般には、無限ループはプログラミングのミスで発生する。すなわち、ループ終了条件がループ内で全く発生しないことが原因で意図しない無限ループとなる。

### 次の繰り返しへの継続

ループ途中でループ処理を中断してループの先頭に戻り、次の繰り返しを開始したい場合がある。言語によってはこれを実現する`continue`や`skip`、`next`といった文を用意している。その効果は最も内側のループ本体の実行を途中で止め、そのループの次の繰り返しを最初から行う。もしそのときの実行が最後の繰り返しであった場合、ループそのものを早期に終了させるのと同じことになる。

### 現在の繰り返しの再実行
Perl や Ruby といった一部の言語では `redo` 文によって現在の繰り返しを先頭から再実行することができる。

### ループの再実行
Ruby では、`retry` 文でループ全体を最初から再実行することができる。

### ループからの早期脱出

カウント制御型ループを使って配列上のデータを検索している際に、必要な要素を見つけたら即座にループから抜け出したいという状況がありうる。プログラミング言語によっては`break`や`exit`、`last`といった文を用意していて、現在のループを即座に抜けてそのループの直後の文に制御を転送する機能を持っている。サブルーチン内のループで`return`を使った場合、入れ子になったループからも脱出することになる。多次元配列を入れ子になったループで検索している場合、若干複雑になる（#提案された制御構造の章参照）。

以下の例はAdaを使ったものである。Ada は「ループからの早期脱出」と「途中にテストのあるループ」の両方をサポートしている。どちらもよく似ているが、コードを比較すればその違いがわかる。早期脱出は`exit`文でただループを脱出する（多くの場合`if`文と組み合わせる）のに対して、途中のテストでは`exit when`文のみで条件分岐と脱出を行う。


```ada
with Ada.Text IO;
with Ada.Integer Text IO;

procedure Print_Squares is 
    X : Integer;
begin
    Read_Data : loop
        Ada.Integer Text IO.Get(X);
    exit Read_Data when X = 0;
        Ada.Text IO.Put (X * X);
        Ada.Text IO.New_Line;
    end loop Read_Data;
end Print_Squares;
```


Python は `break` でループを早期脱出したか否かに依存して、実行されるブロックを指定できる。以下はその例である。


```python
for n in set_of_numbers:
    if isprime(n):
        print "Set contains a prime number"
        break
else:
    print "Set did not contain any prime numbers"
```


Python では `for` 文も `while` 文もこのような `else` 節を使うことができる。else 節は早期脱出が発生しなかったときのみ実行される。

### ループ変化条件とループ不変条件
とループ不変条件は、ループの正しさを表すのに使われる。

典型的には、ループ変化条件とは非負の初期値を持つ整数式である。変化条件はループを回るたびに減少しなければならないが、正しいループ実行の間は負の値になってはならない。ループ変化条件はループが終了するであろうことを保証するのに使われる。

ループ不変条件は、ループを回る前と各反復において真でなければならない表明である。すなわち、ループが正しく終了するには終了条件とループ不変条件が共に真でなければならない。ループ不変条件は、ループ実行中にループの具体的属性を監視するのに使われる。

Eiffelなどのプログラミング言語でループ変化条件とループ不変条件がサポートされている。Javaではアドオンである Java Modeling Language (JML) という仕様で同様のものをサポートしている。

### サブ言語でのループ
Lisp方言では、ループを記述するための多機能なサブ言語を提供することが多い。代表的な例としては、Common Lisp の LOOP が挙げられる。初期の例としては Interlisp の Conversional Lisp がある。

### ループ機能の比較表

## 構造化非局所制御フロー
多くのプログラミング言語、特に動的なプログラミングスタイルを指向した言語では、「非局所制御フロー」の構造を持っている。これを使うと実行の流れは現在のコンテキストから離れ、事前に定義された場所から続行される。「条件」、「例外」、「継続」の3種類の典型的な非局所制御構造がある。

### 条件
PL/I は標準で22種類の条件（ZERODIVIDE、SUBSCRIPTRANGE、ENDFILE など）をサポートし、これを発生(RAISE)させ、ON *condition* action; で解釈することができる。プログラマは独自の条件を定義することもできる。

構造無しの IF 文のように action にはひとつの文しか書けないので、多くの場合 GOTO 文を使って制御フローを継続する必要がある。

しかし、実装によってはこれは空間と時間を無視できないくらい浪費する（特に SUBSCRIPTRANGE の場合）。多くのプログラマは条件を使わないようコードを書くことが多かった。

典型的な文法例:

  **ON** *condition* **GOTO** *label*

### 例外

最近の言語は例外処理を行う構造化された制御構造を備えている。


```cpp
try {
    xxx1                                  // この中のどこかで以下を使用する
    xxx2                                  //     '''throw''' someValue;
    xxx3
} catch (someClass& someId) {             // someClass の場合をキャッチ
    actionForSomeClass 
} catch (someType& anotherId) {           // someType の場合をキャッチ
    actionForSomeType
} catch (...) {                           // 既にキャッチされていない任意の値をキャッチ
    actionForAnythingElse
}
```


任意の **catch** 節が上記の例では使用されている。D言語、Java、C#、Python では `try` 構造に `finally` 節を追加することができる。`try` 部分を離れる際にはどういう理由であっても必ず `finally` 節が実行されることが保証されている。これは処理を終了する際に何らかの高価な資源（オープン中のファイルやデータベース接続）を解放しなければならない場合に便利である。


```csharp
FileStream stream = new FileStream ("logfile.txt", FileMode.Create);                    // C# の例
try {
    return ProcessStuff(stream);             // 例外を発生する可能性がある
} finally {
    stream. Close();
}
```


この例は非常に一般的であり、C# ではこのための特別な構文がある。


```csharp
using (FileStream stream = new FileStream ("logfile.txt", FileMode.Create)) {
    return ProcessStuff(stream);             // 例外を発生する可能性がある
}
```


上記の例の `using` ブロックを離れるとき、コンパイラが自動的に `stm` オブジェクトを解放する。Pythonの `with` 文やRubyの `File.open` へのブロック引数も同様の効果がある。

このような言語はいずれも標準の例外を定義し、それらがどのような状況で発生するかを定義している。ユーザーは独自の例外を発生させることもできる（実際、C++ と Python は任意の型の throw と catch が可能）。

特定の `throw` にマッチする `catch` がない場合、マッチする `catch` が見つかるまで入れ子構造を遡り、サブルーチン呼び出しを遡る。メインプログラムまで遡っても対応する `catch` がない場合、プログラムは適切なエラーメッセージを出力して停止する。

AppleScript スクリプト言語 は "`try`" ブロックにいくつかの情報を提供する。


```applescript
try
    set myNumber to myNumber / 0
on error e  number n  from f  to t  partial result pr
    if ( e = "Can't divide by zero" ) then display dialog "You must not do that"
end try
```


### 継続

### 非局所制御フローの比較表

## 提案された制御構造
ドナルド・クヌースは1974年の論文 "Structured Programming with go to Statements" でそれまでの制御構造でカバーされていない2種類の状況を提示し、それを実現する制御構造を例示した。他にも以下に示すような提案がある。

### 途中にテストのあるループ
これは1972年にダールが提案した。

 **loop**                           **loop**
     xxx1                           read(char);
 **while** test;                    **while** **not** atEndOfFile;
     xxx2                           write(char);
 **repeat**;                        **repeat**;

もし *xxx1* が省略されたなら、テストが先頭にあるループとなる。もし *xxx2* が省略されたなら、テストが末尾にあるループとなる。*while* 文が省略されれば無限ループとなる。このように、ひとつの制御構造で多くのループパターンを表現できる。ありうる派生としてループ内に複数の **while** テストを配置できる拡張が考えられるが、その場合は後述の **exitwhen** の方が適切である。

一般に、任意のループ構造と、条件分岐と**break**を組み合わせて、同様のプログラムを書ける。

 **while** (true) {
     xxx1
     **if** (**not** test)
         **break**
     xxx2
 }

Adaでは、上記のループ構造（**loop**-**while**-**repeat**）の代替として標準の無限ループ（**loop**-**end loop**）内で **exit when**節を使うことで同様の制御構造を実現できる（後述の **exitwhen** 文と混同しないよう注意されたい）。


```ada
with Ada.Text_IO;
with Ada.Integer_Text_IO;

procedure Print_Squares is 
    X : Integer;
begin
    Read_Data : loop
        Ada.Integer_Text_IO.Get(X);
    exit Read_Data when X = 0;
        Ada.Text IO.Put (X * X);
        Ada.Text IO.New_Line;
    end loop Read_Data;
end Print_Squares;
```


ループの命名（この例では *Read_Data*）は必須ではないが、ループの入れ子で外側のループまで脱出させることができる。

### 複数早期脱出と入れ子ループからの脱出
これは 1974年、Zahn が提案した。ここではそれを若干修正したものを示す。

 **exitwhen** EventA **or** EventB **or** EventC;
     xxx
 **exits**
     EventA: actionA
     EventB: actionB
     EventC: actionC
 **endexit**;

**exitwhen** は *xxx* 内で発生しうるイベントを指定するのに使い、イベントはイベント名を文として使用すると発生する。イベントが発生すると対応するアクションが実行され、その後 **endexit** 後の処理に移る。この制御構造はある状況を識別する部分と、その状況でとるべきアクションを明確に区別することができる。

**exitwhen** は C++ 言語の **try**/**catch** 構造と概念的によく似ているが、サブルーチン呼び出しを超えたり任意の値を渡したりしないので、より効率的にできる。また、コンパイラは指定されたイベントが全て発生する可能性があり、それらにアクションが対応しているかどうかをチェックできる。

以下の単純な例は2次元配列から特定の要素を取り出すものである。

 **exitwhen** found **or** missing;
     **for** I := 1 **to** N **do**
         **for** J := 1 **to** M **do**
             **if** table[I,J] = target **then** found;
     missing;
 **exits**
     found:   print ("item is in table");
     missing: print ("item is not in table");
 **endexit**;

### COMEFROM

Datamation誌（1973年12月）に掲載された記事で、R. Lawrence Clark は COME FROM 文を提案し、面白い例をいくつか提示した。それ自体は「GO TO論争に寄与する」と称したジョークであるが、ジャーゴンファイルの記事が指摘しているように、たとえばFortranのDO文は「そこで指定した行番号のある行からそこに飛ぶ」という一種のCOMEFROMであることなど、制御構造の問題に面白い視点を与えるものではある。setjmp/longjmpと関連させた指摘もある。

COMEFROM文はINTERCALという難解プログラミング言語に実装された（INTERCALの実装者はジャーゴンファイルの編集者でもある）。

## 脚注

## 参考文献

* Hoare, C. A. R. "Partition: Algorithm 63," "Quicksort: Algorithm 64," and "Find: Algorithm 65." Comm. ACM 4, 321-322, 1961.

## 関連項目
* 分岐命令
* goto文
* サブルーチン
* イベントループ
* 再帰呼び出し
* スパゲティプログラム
* 構造化プログラミング
* 関数型プログラミング
* 制御抽象化
* 制御フローグラフ
* コルーチン
* 循環的複雑度
* フローチャート

## 外部リンク
* Go To Statement Considered Harmful
* A Linguistic Contribution of GOTO-less Programming
* Structured Programming with Go To Statements
* IBM 704 Manual