トップ «前の日記(2008-06-06) 最新 次の日記(2008-06-08)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2008-06-07

_ トリッキーなコード

昨日書いたリストを眺めていて、やっと「トリッキーなコード」という言葉の意味を理解したように思えた。

トリッキーという言葉が意味することは「奇をてらったさま。巧妙なさま。「―な仕組み」」なので、奇をてらってはいるけれど、考え通りに動く=巧妙なコードという意味だろう。

女子高校生風に考える(良くわからないことにしておくが、こういう場合、JKと書くものらしい)と、途中のコードをスキップして制御を移動させる場合はgotoというステートメントを使うものだ。Cの言語仕様ではそうなっている。

したがって、常識的で、まったく奇のてらいがない、普通のコードであれば

int foo() {
    int result = ERROR_EXIT;
    if (foobar() != SUCCESS) goto error_return;
    if (barbaz() != SUCCESS) goto error_return;
        ...
    ...
    result = SUCCESS;
error_return:
    return result;
}

と書くところだ。

これは、しかし、do……whileを使った(修正済み:コメント欄参照)トリッキーなコードでも記述できる。

int foo() {
    int result = ERROR_EXIT;
    do {
        if (foobar() != SUCCESS) break;
        if (barbaz() != SUCCESS) break;
        ...
        result = SUCCESS;
    } while (0);
    return result;
}

これがトリッキーなのは、本来、「偽になるまでループ」するために利用するwhileを、breakによって節から退出できることを悪用してgotoに代替させている点にある。そもそも論では、あらかじめ条件式に偽を設定するところからしてトリッキーだ。

僕が良く耳にする女子高校生なコーディング規約は、「トリッキーなコードは禁止」というものだ。ふむ。

どうやら、トリッキーなコードを許容できるくらいに、gotoを使うことに無意味(この場合に意味ありますか?)な拒否反応があるのだろう。

おもしろい。

_ 女子高校生的に考えることの重要さ

そこで考えるのだが、ダイクストラの時代であればともかく、while、do……while、さらにはforといった至極便利極まりないステートメントを持つ言語を利用していて、あえてgotoを使う人がいるのだろうか?

昔の人はそうだったかも知れない。はじめてwhileだのdoだのを目にした人が、「かーっ! こんなまだるっこしいもの使ってられるかってんだ」とgotoを使うというのは、まあ、理解できなくはない。

しかしだよ、今この時点で、

for (int i = 0; i < 10; i++) {
    if (a) {
      continue;
    } else if (b) {
      break;
    }
    ...
}

と書かずに、わざわざわざと、

    int i = 0;
start_loop:
    if (i >= 10) goto exit_loop;
    if (a) {
        i++;
        goto start_loop;
    } else if (b) {
        goto exit_loop;
    }
    ....
    i++;
    goto start_loop;
exit_loop:
    ...

なんて書くかね? 本気でそう信じているのか?

そう信じているなら、イワシの頭賞を進呈する。どうぞご自由に。

しかし、女子高校生風に考えれば、そんな面倒なことをする人間はいない。

であれば、goto禁止というのは取り下げたほうが良い。

そうすれば、「このgotoというステートメントは何の役に立つんだ?」となるだろう。

そこで、「エラーになったら、エラーリターン用のラベルへ分岐するために利用したり、深い制御構造の中から脱出するために利用するんだよ」で済むではないか。

10年ドロドロおじさんの悪口を言うのも結構だが、ドロドロおじさんと同じレベルで「禁止」とか無定見に言ってないか、考えてみても良いと思う。

本日のツッコミ(全6件) [ツッコミを入れる]
_ ささだ (2008-06-07 03:36)

while(0) じゃ通らないっす.do/while(0) かな,とは思うんですが.

_ arton (2008-06-07 04:18)

ははは。本当ですね。直しました。どうもありがとうございます。

_ arton (2008-06-07 04:21)

しまった。このくらいトリッキーなコードは危険だ、とかなんとか入れておくべきだった。

_ みずしま (2008-06-07 10:11)

便乗してどうでもいいツッコミですが、next;じゃなくて<br>continue;ではないかと。

_ arton (2008-06-07 10:33)

ううむ、まったく説得力をなくすバグの連続。後で直しておきます。ありがとうございました。

_ arton (2008-06-07 10:37)

あれ? 更新できたぞ。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|

ジェズイットを見習え