goto文とその他諸々

ちょと前のエントリid:masugataさんのところからトラックバックが来ていることにビックリしつつ。goto文とその他諸々についてのお話。
goto文の存在意義についてはやっぱり疑問は多いですよね。


例外処理が無い言語やLoop処理がネストしまくった状態で一気に抜ける事が出来ないような言語ではgoto文の意義は(それなりに)あったようにも思えますが、最近の言語的にはどうなんでしょうか。
まさしくこの通りで。

で、ネストしまくりのループを一気に抜けることができる言語であるPHPで、gotoが必要になる状況を考えてみました。
以下はコマンドラインとかバッチ処理かなんかでコマンドを処理していると思ってください。あるいはチューリングマシンのシミュレータかもしれません。その辺はご想像にお任せしますが、

<?php
while(true) {
    $a = getInput(); // aになんか配列の形した入力をもらってくる。
    $len = count($a);
    for($i = 0; $i < $len; $i++) {
        switch($a[$i]) {
          case 'q':
            break 3; // アプリケーション終了などで無限ループ抜ける
          case 'a':
            dosomething($a, $i); //とりあえずなんかします。
            break;
          case 'r':
            break 2; // もう一度入力をもらいに行く
          default:
            echo '知らない入力だ!', PHP_EOL;
        }
    }
}
?>

これよりも

<?php
while(true) {
  get_new_input:
    $a = getInput(); //aになんか配列の形した入力をもらってくる。
    $len = count($a);
    for($i = 0; $i < $len; $i++) {
        switch($a[$i]) {
          case 'q':
            goto finalize_app; // アプリケーション終了などで無限ループ抜ける
          case 'a':
            dosomething($a, $i); //とりあえずなんかします。
            break;
          case 'r':
            goto get_new_input; // もう一度入力をもらいに行く
          default:
            echo '知らない入力だ!', PHP_EOL;
        }
    }
}
finalize_app:
?>

こちらの方が見通しがよくなる気がします。前者だとswitch文の前にもうひとつループが増えたりしたら一番外まで行くためのbreak 3をbreak 4に変更しなければいけません。見落としてしまいそうです。しかし後者なら行き先がラベルで示されているのでループが増えてもそのままでOKです。
goto文て意外といいものかもしれません。

さて、話は変わって

コメントにあったマクロや#ifdefの機能は。。。どちらも乱用してしまうと見通しが悪くなるので、PHP的にはmustな機能ではないかな、と思いますが、あると便利な局面があるかもしれません。

これですが、#ifdefやマクロを使う場面はフレームワークやライブラリを想定していました。これらは環境を判断するためにif文を用いることがありますが、現在は毎回そのif文が実行されます。もちろん中間コードキャッシュを使っていても同様です。もし、この処理が初回起動時(コンパイル時)だけしか行われなくなったら多少の速度向上と中間コードの削減*1という利点が生まれます。と思うのですがどうでしょうか。

まぁ、この辺はPHPerらしからぬ発想なのかもしれません。

*1:使われない部分は削ってしまえる