余談だが、同様に名前が決定的にものを言うのは、パッケージソフトの名前で ある。性能が数倍優れているよりも、名前が明快な方がよく売れるのではないか。 ここで勘違いしてはならないのは、何をもって明快とするか、ということである。 覚えやすく、雰囲気ぴったりで、かといって自己満足的だったり、凝りすぎて嫌 みを感じさせることがない、そういう名前を付けるのは実に大変なことなのだ。 しかし、どうも ABC-123 のような感じのパッケージソフトが今も売られているい うのが、いまいち釈然としない。
話はC言語フォーラムに戻る。ここにはQ&Aの電子会議があって、回答好きな 人達(失礼)が競って回答しているが、私も希に仲間に加わったりする。主に初 心者への回答を狙うことにしている。なぜかというと、高度な質問だと答がわか らないからだが。
さて、私は回答の最後に練習問題を付ける癖がある。本当に練習問題のこともあ るが、実は私も分かっていなかったりするので、練習問題という名目にして逆に 質問していることもあるとはお釈迦様も御存じあるめえ。ちょっと前になるが、 摩化不思議な問題を書いた。その話も、元はといえば、ある人の質問から話が始 まったのである。最初から書くと長くなって頁に収まらないから、最後に私が出 した問題のみ引用してみよう。
(ラムとあたる、ラーメン屋に入る)
ラム 「うち、カレーの方がいいっちゃ。」
あたる「なぜそれを先に言わんのだ!」
(ラムとあたる、ラーメン屋を出る)
問題:ラムとあたるがラーメン屋に入ったのはなぜか? ※
例えば、あたるがラムもラーメンを食べると思ったから、という感じの答でいい かもしれない。ではなぜそう思ったのか。そうなると難しい問題である。え、ど こがC言語に関係あるのかわからない? いや実は関係ないのですが。いや、全 然無関係というのではなく、少しは関係あるのですが。余計わからない? それ は困りましたねえ…。
*
いきなりC言語になる。
リスト1は、改行のコードの組を CR+LF に整形する処理のつもりである。
/* リスト1 */
/* 行末のコードの組をCR+LFに整形する */
#define LF 0x0a
#define CR 0x0d
void set_end_of_line(FILE *in_fp, FILE *out_fp)
{
int c;
while ((c = getc(in_fp)) != EOF) {
if (c == CR) {
/* 読みとばす */
} else if (c == LF) {
putc(CR, out_fp);
putc(LF, out_fp);
} else {
putc(c, out_fp);
}
}
}
CR+CR+LF の行末になっていると書いたが、以下の考察では、この順序であ ることがポイントになるので、頭に入れておいて欲しい。 仮にLF、CRの順序で比較すれば、
CRが現われる ---> LFと比較するが、一致しない
CRと比較して一致する。
LFが現われる ---> LFと比較して一致する。
このように3回の比較で処理が終了する。この場合は、先にCRと比較して、後か
らLFと比較しても回数は変わらない。では、CR+CR+LF だとどうか。LF を先にチ
ェックした場合は、
読んだ文字 比較する文字
------------------------------
CR LF 一致しない
CR 一致する
CR LF 一致しない
CR 一致する
LF LF 一致する
で5回の比較となり、CR を先にチェックする場合は、
読んだ文字 比較する文字
------------------------------
CR CR 一致する
CR CR 一致する
LF CR 一致しない
LF 一致する
で4回の比較ですむのだ。
なお、NIFTY-Serve のデータライブラリに登録されているデータの中には、改行 コードがCRのみになっているものがたまにある。 このような行末と「CR+LF」という行末 が混じったデータの処理を書く場合にも、 CR、LFの順序で比較し たほうが比較の回数は少なくてすむ。
さて、ここで問題は、c を CR、LF の順序でチェックしているのはなぜか、とい うことである。ここまできたら、比較の順序の理屈は分かるだろう。データによ っては、必ずしもこれが最善になるとは限らないのだが、一応理屈を考えたとい う点では評価してもよいと思う。後は、実際にプログラムを走らせて、どの程度 差があるかを調べるとよい。おそらく、殆ど差がないのでがっかりするかもしれ ない。
「ラムとあたるがラーメン屋に入ったのはなぜか?」という問題に戻るとこうで ある。まず、あたるが最適な行動をすると仮定しておく。ならば、単純に考えれ ば、ラーメン屋に入る前にラーメンを食べるかどうか尋ねるのがセオリーである。 そうすれば、ラーメンを食べないのにラーメン屋に入ってしまうという無駄な行 動をしなくてすむからだ。しかし、あたるがラムに対してラーメンを食べること にまず同意するに違いない、という予想をした場合には、まず間違いないことを わざわざ確認する手間の方が無駄であるから、とりあえずラーメン屋に入ってし まった方が、トータルとしては能率的かもしれない。このように、状況によって どれが最適になるかわからない場合には、話はえらいややこしくなるのだ。
*
このような姑息なオプティマイズは、近い将来、ダイナミックなオプティマイズ
が実現すればプログラマーの責任から解放されることを信じたい。つまり、処理
中に頻度の高い一致を統計処理して、よく現われる文字を最初に比較するように、
プログラムが処理をしながら自分自身のコードを変えてしまえばよい。仮名漢字
変換処理の学習機能をイメージしてもらえばよい。これがあらゆるコードに作用
する。ちょっと怖い気もするが。
しかし、結局肝心なのは、プログラマーの心意気。少しでも工夫してやろう、と いう気構えである。調子に乗りすぎると、最適化はされたが訳のわからんプログ ラムになる危険もあるかもしれないが、とりあえず心意気が重要なのだ。これが なければ、プログラムはいくらでも堕落する。まあ動かないプログラムもよくあ る話だから、とりあえず動けばよい、というのも説得力があるには違いないのだ が。
※問題の答 あたるの腹がへっていたから