Cogito Ergo Sum.

我思う故に我あり

プログラムは「後戻り」できない。

 半年振りにC#でプログラミングしていて、我ながらギョッとするコードを書いてしまった。

 これは架空の例だが、今、5枚の絵を表示する絵本プログラムをつくっているとして、5枚の絵はそれぞれ全然違う形式なので同一の関数を使えないものとする。それで僕は、1ページ目の絵を表示する関数bool p1(void)、2ページ目の絵を表示する関数bool p2(void)、…、5ページ目を表示する関数bool p5(void)を作った。

 で、1ページ目から5ページ目まで順番に表示したかったので、
result = p1();
result = p2();
result = p3();
result = p4();
result = p5();
 みたいなコードを書いた。

 ところが、途中で思い直して、「後戻り」もできるようにしたくなった。あるページを見た後かならず次のページを表示するのではなく、前のページにも戻れるようにしたい。それを実現しようとしたら、こんな感じのコードになってしまった。
do {
 result = p1();
 do {
  if (! (result = p2())) break;
  do {
   if (! (result = p3())) break;
   do {
    if (! (result = p4())) break;
    result = p5();
   } while (! result);
  } while (! result);
 } while (! result);
} while (! result);

 我ながら何とも奇っ怪な多重ループ構造のお目見え…(これ、架空の例なんで、本当にこれで正しいのかちょっと自信がないのですが、要するに「多重ループ構造になった」ということを言いたい)。

 自分でこんなコードを書いておきながら、「『行ったり来たり』したいだけなのに、なぜループの入れ子構造になるのか」がしばらく理解できなかったのだけど、「要するに、プログラムは『後戻り』できないんだ」ということで納得した。

 通常、プログラムは「上から下へ」実行される。「下から上へ」実行されることはない。唯一の例外が「繰り返し」構文を使ったとき。僕はこれまで、forだとかdo-loopなんかの「繰り返し」構文は、文字通り「繰り返し」を実現するためだけに用いるものだと思っていた。

 ところが、考えてみれば、「後戻りする」ときにも「繰り返し」構文を使わざるを得ない。プログラムの実行箇所を「下から上へ」ジャンプさせることができるのは「繰り返し」構文しかないのだ。

 そうやって考えてみると、「3ページを見た後で、4ページを見て、その後また3ページを見て、更に2ページに戻り、再び3ページを見て…」みたいな、「いつまで経っても終わらない」感は、上の多重ループ構造によく表われているようにも思う(意外かもしれないが、プログラミングに没頭していると、一見無機質なように見えるプログラムに「気分」を感じ取れるようになってくる)。

 もちろん、最初から「後戻りもできるような設計にしよう」と考えていれば、上のようなコードを書かずに済むような方法を考えたのだけど、途中で方針転換したものだから、こんなことになってしまった。ただ、そのことで「プログラムは単純なかたちでは『下から上へ』実行できない」という、当然の事実に改めて気づくことができた。これも怪我の功名と言うべきか…。