たまたま、このページ(元は404になっていたので、グーグルのキャッシュ?のページより)を見つけました。
あ、
計算論 計算可能性とラムダ計算
http://www.amazon.co.jp/gp/product/product-description/4764901846
ですね(^^)/
これの、12ページ、定理1.2.1の話ですね。
任意のNプログラムに関して、whileプログラムが存在する
Nプログラムっていうのは、簡単に言うと、
・代入文(っていうか、なんか処理する文)
・条件分岐文
・入力文
・出力文
でできていて、この順番は、矢印引っ張って(有向グラフ)、どこでもいけるってもの。
つまり、これは、プログラムだと、GoTo文使って、どこでもいけるっていうこと。
一方、Whileプログラムは入れ子にはできるんだけど、入れ子が交差するようなことはできない。
いわゆる、GoToレスなプログラムですね。
つまりこれは、
あらゆるGoTo文を使ったプログラムはGoToレスなプログラムに出来る
ってことなんだけど、この証明、そのリンク先より、実務的には、もっと面白いので、ちょっと書きますね。
■方法
(1)まず、元のNプログラムをGOTO文をつかって、かきますね!
(上記の本の12ページの図3)
input x TOP: if ( a == true ) GOTO OUTPUT else b(); if ( c == true ) e(); GOTO OUTPUT else d(); GOTO TOP endif endif OUTPUT: output y
(2)全部の処理の頭に、ラベルを振ってください
本では、0、1と振ってあるのですが、数字だとわかりにくいので、
ZERO,ONE,TWOと、英語で振りますね。また、TOPはZERO,OUTPUTはFIVEなので、
そのように書き直します。
input x ZERO: if ( a == true ) GOTO FIVE else ONE: b(); TWO: if ( c == true ) FOUR: e(); GOTO FIVE else TREE: d(); GOTO ZERO endif endif FIVE: output y
(3)b()のような普通の文の場合、下の行にいきます。
IF文は、TRUEの場合、FALSEの場合で行き先が分かれます。
GOTO文が書かれていないところに対して、
普通の文ならGOTO次の処理のラベル
IF 文は GOTO TRUEのとき、GOTO FALSEのときで書き直します。
input x GOTO ZERO ZERO: if ( a == true ) GOTO FIVE else GOTO ONE endif ONE: b(); GOTO TWO: TWO: if ( c == true ) GOTO FOUR ELSE GOTO THREE ENDIF FOUR: e(); GOTO FIVE TREE: d(); GOTO ZERO FIVE: output y
(4)ここで、ステータス変数u(本ではプログラムカウンタになっている)を利用しましょう。
・GOTO 何とかのところを、u = に書き換え
・それぞれのラベルをcaseにして、switch文に置き換え、
・全体をwhileでくくります。
そうすると・・・
u = START while(u != END) { switch(u) { case START: input x; u=ZERO; break; case ZERO: if ( a == true ) u = FIVE; else u = ONE; endif break; case ONE: b(); u = TWO; break; case TWO: if ( c == true ) u = FOUR; ELSE u = THREE; ENDIF break; case FOUR: e(); u = FIVE; break; case TREE: d(); u = ZERO; break; case FIVE: output y u = END; } }
ちゃんとしたプログラムではないけど、こんなかんじ。
■つまり、
上記のuをイベントと考えれば、上のプログラムは、まさにイベントドリブンなわけで、
結局、
GOTOを含むようなプログラムは、イベントドリブンのGOTOレスプログラムに置き換えられる
ってわけ。
イベントドリブンって、強力だよね(^^)/