Home日記コラム書評HintsLinks自己紹介
 

フィンローダのあっぱれご意見番 第113回「宗教的プログラミング」

← 前のをみる | 「フィンローダのあっぱれご意見番」一覧 | 次のをみる →

@niftyの「プログラマーズフォーラム・オリジナル」で、 プログラマーと宗教に関する会議を開催してみたのだが、 発言の印象として、 昔に比べるとプログラマーが「普通の人」化しているような気がする。 昔はどんな雰囲気だったのかというと、 言語はPerlじゃないとダメだとか(あるいはPerlだとダメだとか)、 LISP (って今でも通じるのか?)よりは Prolog がいいとか、 根拠があるのかないのか分からないが信仰している人が結構いたものだ。 いや、今もいるのかもしれないが、 あまりにもこだわりのない「普通の人」的プログラマーが多くなって、 世界が変わってきたような気がするのだ。

 

※ プログラマーズフォーラム・オリジナル: FPROGORG。 2005年9月末に@niftyでの活動終了。 その後地下に潜伏中。

ところで、キリスト教に聖書があり、イスラム教にコーランがあるように、 プログラマーに何か経典があるとしたら、それは一体何だろうか。 Knuthの本だとか、あるいは書法、作法になるのだろうか。 最近のプログラマーは、 もしかしたら「1週間でできる○○」みたいな本しか持ってなかったりしそうで恐い。 まあそれは極端だとしても、 Webの情報を参考にすれば情報は結構手に入るから、 もしかしたら 本を持っていないなんて人がいるかもしれない。 Javaの勉強を一から始めたいなら、 素質のある人なら、Sunのサイトを見るだけで多分マスターできるだろう。

 

※ Java のチュートリアルはかなり充実している。 Sun の他だと、 IBM の developerWorks のドキュメントも勉強になる。

ルール的な部分をドキュメントで大雑把に飲み込んで、 実技は公開されているソースを読んで勉強するとか、そういう人もいるだろうか。 "Use the source." というギャグがあった位だし、 ソースを読むというのは根本に帰るという感じで正統派の姿だと思う。 ただ、GUI系の統合環境を使ったりする場合、 確かにソースを読むとそれなりの知識は身に付きそうだが、 自動生成されたコードをいくら読んでも、 「○○のウィンドウにテキストボックスを配置してラジオボタンで処理内容を選ばせるにはどうすればよいか」 のような問題は解けない。 なぜなら、それを解くのに必要なのは、 プログラミング言語の知識ではなくて、 統合環境の操作方法だからだ。 もっとも、統合環境なんか使わずに全部コードを書いてやるというツワモノだって、 もしかすると実在するかもしれないわけだが。

 

※ 「かもしれない」ではなくて本当に実在する。

§

最近、学校の課題についてメールで質問してくる人が少し増えたような気がする。 一般的に、BBSとかnewsgroup においては、 課題の解答を質問することはご法度になっていることが多い。 理由は、自分で解かなければ意味がないというか、 解答を丸写しにすることで単位をもらうだけで、 本人は全く理解する気すらなかったりするからだろう。

  

それはそれで構わないという考え方もあるし、 個人的には、こういう課題に回答するのは好きなのだ。 本人のためにならないことって、最高。 しかし、一般的には無償奉仕でかつ誰のためにもらない、 というような労働はイヤだという人の方が多いのだと思う。 また、現実的には、それを回答する時間もなかなかなかったりする。 極めつけは、 簡単なような課題が意外と難しいことが多くて、実際困ってしまうのである。

 

※ 質問した人のためにならなくても、 別に私は困らない。 自分の勉強になるのであれば、回答する意味は十分にあるのだ。

特に気になるのが、「○○の言語で××という処理を書け」的な問題だ。 というのは、その人が言語について全く分からないというのは仕方ない。 ある程度分かっていたら質問してこないような内容なのだ。 問題は、その人がプログラミング一般に対する知識がないように思われる場合だ。 「ループって何?」のような感じの人にプログラムを書かせるというのは、 ちょっと無茶すぎると思うのだが。 では私がプログラミングを始めた頃に、 何かプログラミングに関する一般的な知識があったかというと、 どうだろう。 フローチャートを書く程度はあったかもしれないが、 かなり早い時期からコーディングを始めて、 実際にプログラムを動かしながらノウハウを身に付けていったような気もする。

§

  

最近あった質問で、多分、画面上にテキストでグラフを書かせる課題というのがあった。 多分というのは、 質問の内容が曖昧なので、よく分からないのだ。 課題を受けている人達は、その授業における暗黙の了解事項を共有している。 表には出てこない条件を使って、問題を解くことができるのである。 質問にはそれが出てこないので、どこまで考えてよいか分からないわけだ。

 

※ それ以前の問題というか、 日本語の勉強を先にやった方がいい、という場合も結構あると思う。

どんな課題か要約すると、あらかじめユーザにキーボードから1か2を入力させて、 それに応じて別々のグラフを表示させるというような感じの設問だった。 グラフは、xの値が1から20までの値を計算して、 それに応じた数の「*」というキャラクタを画面表示するという感じで実現する。 GUIじゃなくてCUIってことだ。 C言語の演習としては妥当だろう。

 

※ C言語の仕様には GUI の規定がないので、 言語の演習で GUI まで扱うのは範囲を逸脱している、という意味。

ここで困ったのが、プログラムの構造をどうするかということだ。 仮に、mode という変数が0かどうかでグラフの種類を判定するとして、 ループの外にグラフを選択するための判定処理を置くと List 1 のような構造となり、 ループの中に置くなら、 List 2 のような構造となる。

---- List 1 (ループの外で判定) ----

    if (mode == 0) {
        for (x = 1; x <= 20; x++) {
            print_function_1(x);
        }
    } else {
        for (x = 1; x <= 20; x++) {
            print_function_2(x);
        }
    }

---- List 1 end ----
---- List 2 (ループの中で判定) ----

    for (x = 1; x <= 20; x++) {
        if (mode == 0) {
            print_function_1(x);
        } else {
            print_function_2(x);
        }
    }

---- List 2 end ----

さて、List 1 と List 2 は、どちらがよいのだろうか。

プログラミングにおける重要な法則の中に、 「同じことを実現する方法はいくらでもある」というものがある。 単に変数名が違うというレベルの話ではなく、 根本的なアルゴリズムからして異なることも珍しくはない。 ここではコードの性質がちょっと違う、 という程度で済んでいるから比較も簡単だ。 ぱっと見た感じでは、List 2 の方がすっきりしているだろう。

具体的に考えるなら、 ループが1個所しか出てこないというのがいい。 このことは保守性において重要な意味を持つ。 ループの回数を20ではなく40にしろという仕様変更があった場合どうだ。 1個所を修正すればよいのなら間違うことはまずないのだが、 2個所を修正しなければならない場合、 片方を修正し忘れるというリスクが常に伴う。 それを避けるには、 C言語だと、マクロか変数を使って、 少なくとも見かけ上は変更する個所を1つに絞るのが効果的だ。

ところが、効率を考えるならば、List 1 の方が望ましい。 なぜなら、List 1 は mode の比較は一度しか行わない。 List 2 は、ループの中で、 結果がわかりきっている比較を20回も行うのである。 とはいっても、20回というのがこれまた問題だ。 20万回とか20億回ならともかく、 たった20回程度ならたいしたことはない、という気もするのだ。

§

  

あと、細かい話ですけど、1から20までのループの終了条件判定を 「x <= 20」と書いているのだが、これは「x < 21」とも書くことができる。 どちらがよいだろうか? 「20まで」という意味を表現しているのは「x <= 20」である。 整数値を使えば小数点以下の問題は発生しないから、 こう書いても何も不明瞭なことはない。 もちろん、 実数をループ変数にしないというのも、基本的なプログラミングの教えの一つであるから、 あたりまえの話なのだが。 とりあえず、「100回ループさせる」という処理を書く場合の定石は、 List 3 のような書き方である。

 

※ 変化させたい値が実数の場合、誤差が発生するので、 この2つの書き方は意味が違ってくる。 しかし、ループ変数は実数ではなく整数値にする、というのが定石。

---- List 3 ----

    for (i = 0; i < 100; i++) {
        /* ループさせたい処理 */
    }

---- List 3 end ----

0から始まって99まで実行したらちょうど100回、というのがC的100回である。 1から100まで、というのではないのがポイントだが、慣れないと違和感があるのだろうか。 なお、 この場合は「i <= 99」と書くこともできるが、「i < 100」の方がいい。 「100回」ループしたいという意志が感じられるからだ。

この課題を出した先生は、 実はかなりやり手なのかもしれない。 単純な問題のようで、奥が深いのである。

§

「C言語を始めたいのだが、どの教科書がいいですか?」 という質問は昔からあったのだが、長年研究しているわけではないし、 どうも最近の本はよく分からないので回答が思い浮かばない。 気のせいかもしれないが。 個人的には、 原著があって翻訳してある系の本が、確率的にいいものが多いと思っている。 もちろん、日本人が書いた本はダメだとか言うのではない。 名著もあるはずだ。 具体的には…とかいわれたらちょっと困るのだが。 とにかく、最初に読む本というのは、 前知識がないだけに信仰に近いレベルで鵜呑みにしてしまうリスクがあるから、 真剣によいものを選ばないといけない。

私がC言語を始めた頃は K&R の「プログラミング言語C」 という本しかなかった時代だったから、迷うことはなかったが、 この本は確かにいい本だ。 ただ、これを読んだら Windows のアプリケーションを書けるのかとか、 リモートデータベースをアクセスするコードが書けるかというと、 そういう話とはまるで次元が違っていて、 むしろ「プログラミング」という行為にかなり近いレベルの話が出てくる所がいいと思うのである。

まあ、翻訳系の本の方がいい、というのもある意味宗教か。

  

(C MAGAZINE 2001年11月号掲載)
内容は雑誌に掲載されたものと異なることがあります。

修正情報:
2006-03-03 裏ページに転載。

(C) Phinloda 2001-2006, All rights reserved.