トップ «前の日記(2008-05-26) 最新 次の日記(2008-05-28)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2008-05-27

_ わざとバグを入れたCの入門書

翔泳社の編集の方から献本していただいたので、読んでみました。

デバッグではじめるCプログラミング(山本 貴光)

今更、おれが読む本でもないしと思わないでもなかったけど、読んでみるものだ。おもしろかったし、参考になった点もあった。

全体としてはゲームを作る本で、BC++をCで使うことを前提にしている。なぜBC++と大きい疑問を感じたけれど、エラーメッセージの適切さが理由のようだ(とは書いていないが)。

最初に、簡単な出力、入力があって、ちゃんとカタカナでprintfはプリントエフと読みますとか、scanfはスキャンエフと読みますとか読み方も指南している。

で、ゲームを作るというのはどういうことかという読み物ふうのエピソード(著者の方は光栄に勤めていたらしい)が来て、企画とおおざっぱな仕様が来て、では実装していきましょうと話が続く。

で、リストをその通りに打たせるわけだが、タイポもあれば型エラーもある。コンパイルすればエラーになるので、こういうことをすることこういうエラーになる。その理由はこれこれです。修正するにはこうします。つまり、これこれするときには、こうしなければなりません、という調子でおまじないとは言わずに、書き方を説明していく。ゲームを題材というか教科を進めるためのエンジンにしているけど、ゲームプログラミングの本というわけではなく(ただ、ユーザビリティなどについてのある意味実証的な解説が入ったりもするし、プログラムを拡張していくためのユースケースはゲームのシナリオにそって出現する)あくまでもCの入門書だ。最終的には、ダンジョンのマップを格納する2次元配列が出て来て、位置情報から移動の可能性を求め、構造体を利用してキャラクタデータを保持して、さらには当たり判定をして、最後はポインタを利用することでグローバル変数の利用を抑制できることやスコープについて解説して終わる。流れを追うと実は正攻法だ。

結局、おれには迂遠だが、こういうのもありだろうなと思うし、学習の流れのつけ方には感心した。口調も良いし適度に脱線したりするところが妙にリアルなのだが、著者の経歴をみると専門学校で教鞭を取られているようだから、そのあたりから身につけた呼吸なのかも知れない。

追記:著者の山本さんの「あとがき 増補版」

_ 名前付きパラメータと位置によるパラメータの一致の不一致

えのさんが「named arguments considered harmful」というのを書いている。怒っているのがよくわかるのだが、と、ここまで書いてパーマネントリンクを取りにRSSリーダからはてなへ飛んだら、おれが書きたかったこと(ちょっと違うが)を成瀬さんがコメント欄で指摘していた。もっともole2disp.dllが頑張っていたおかげで、90年代からIDispatchインターフェイスの仮引数名は同じ問題を抱えていたから、意識改革しかないよなぁという気もしないでもない。

名前付きパラメータがえのさんの指摘のように不幸なことになるのは、位置によるパラメータと一致していることか、または仮引数名を集合として書けないことによると思う。

少なくとも、&keyの後ろだったら、追加すれば良いだけだろうし。

名前付きの名前を次のように書ければ、おそらく問題とはならず(実装は面倒だとは思うが)、位置によるパラメータとも矛盾しない。

public void foo([name="langage"][name="language"]string langage);

([]はキー名として利用可能な値を属性として提示)

あるいは、RubyのHashを使う方法ではないけれど、位置はあきらめてしまって(速度的なペナルティが付く)

public void foo([type="System.Collections.IDictionary", name="lang"]string langage, string language)

というように書けて、定義側では if (lang["langage"] != null || lang["language"] != null)とかしてアクセスするようになっていれば良いのかも。

属性で位置を生かすというのも考えた。重複した場合のエラー判定が必要だけど、定義側は楽だ。

public void foo([index=0]string langage, [index=0]string language, [index=1]string message);

最悪のシナリオは、キー名違いのオーバーロードだな。

public void foo(string langage) {

foo(language = langage);

}

public void foo(string language) {

……

}

本末転倒という感じがぷんぷんする。

名前付き引数が呼び出し側からみた場合に便利なのは、インターフェイス定義からテンプレートが自動生成できることや、ソースコードの自動生成する場合に与えられたパラメータを仮引数名と関連付ければ済む(不足している場合に位置を意識しなくともかまわない)ことだとは思うが、こればっかりは使っていないのでわからないけど。(Excelのようにパラメータが無駄に50個くらいある場合には、確かに必要な引数だけ用意すれば良いので便利だとは思うが(ある意味では、引数の指定方法によるポリモーフィズム(逆転しているけど)と言えなくもない。同じメソッド名が指定した引数によって処理の意味が変わるから)、現在のVBアプリケーションに必要かというと怪しい)


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|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|

ジェズイットを見習え