余談だが、同様に名前が決定的にものを言うのは、パッケージソフトの名前で ある。性能が数倍優れているよりも、名前が明快な方がよく売れるのではないか。 ここで勘違いしてはならないのは、何をもって明快とするか、ということである。 覚えやすく、雰囲気ぴったりで、かといって自己満足的だったり、凝りすぎて嫌 みを感じさせることがない、そういう名前を付けるのは実に大変なことなのだ。 しかし、どうも 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 の順序でチェックしているのはなぜか、とい うことである。ここまできたら、比較の順序の理屈は分かるだろう。データによ っては、必ずしもこれが最善になるとは限らないのだが、一応理屈を考えたとい う点では評価してもよいと思う。後は、実際にプログラムを走らせて、どの程度 差があるかを調べるとよい。おそらく、殆ど差がないのでがっかりするかもしれ ない。
「ラムとあたるがラーメン屋に入ったのはなぜか?」という問題に戻るとこうで ある。まず、あたるが最適な行動をすると仮定しておく。ならば、単純に考えれ ば、ラーメン屋に入る前にラーメンを食べるかどうか尋ねるのがセオリーである。 そうすれば、ラーメンを食べないのにラーメン屋に入ってしまうという無駄な行 動をしなくてすむからだ。しかし、あたるがラムに対してラーメンを食べること にまず同意するに違いない、という予想をした場合には、まず間違いないことを わざわざ確認する手間の方が無駄であるから、とりあえずラーメン屋に入ってし まった方が、トータルとしては能率的かもしれない。このように、状況によって どれが最適になるかわからない場合には、話はえらいややこしくなるのだ。
*このような姑息なオプティマイズは、近い将来、ダイナミックなオプティマイズ が実現すればプログラマーの責任から解放されることを信じたい。つまり、処理 中に頻度の高い一致を統計処理して、よく現われる文字を最初に比較するように、 プログラムが処理をしながら自分自身のコードを変えてしまえばよい。仮名漢字 変換処理の学習機能をイメージしてもらえばよい。これがあらゆるコードに作用 する。ちょっと怖い気もするが。
しかし、結局肝心なのは、プログラマーの心意気。少しでも工夫してやろう、と いう気構えである。調子に乗りすぎると、最適化はされたが訳のわからんプログ ラムになる危険もあるかもしれないが、とりあえず心意気が重要なのだ。これが なければ、プログラムはいくらでも堕落する。まあ動かないプログラムもよくあ る話だから、とりあえず動けばよい、というのも説得力があるには違いないのだ が。
※問題の答 あたるの腹がへっていたから