2005年02月24日

Invokeメソッド

   このエントリーをはてなブックマークに追加 Clip to Evernote
リフレクションのInvokeメソッドを使うとき、パラメータの与え方でバカをやってしまいました。
MyClassにあるstaticメソッドのMaxが以下のように定義されていた時に、
   public static double Max(double[] nums);
本来は、
  Type type = Type.GetType("MyClass");
MethodInfo minfo = type.GetMethod("Max");
double[] obj = new double[] { 1, 2, 3, 4, 5, 8, 2 };
object[] prm = new object[1] { obj };
double ans = (double)(minfo.Invoke(null,prm));
と書くべきところを
  Type type = Type.GetType("MyClass");
MethodInfo minfo = type.GetMethod("Max");
double[] obj = new double[] { 1, 2, 3, 4, 5, 8, 2 };
double ans = (double)(minfo.Invoke(null,prm));
と書き、なぜ、例外が発生するのか悩んでしまいました。
これだと、7つの引数がある、Max を呼び出していることになりますが、それに気が付きませんでした。

トイレに行くのに席を立ち、廊下を歩いているときに、「あっ、そうか」と、間違った理由がわかりました。
結構、一息入れた時に間違いの原因に気が付くことってありますよね。  

Posted by gushwell at 20:50Comments(0)TrackBack(0)

2005年02月23日

== 演算子のオーバーロード

   このエントリーをはてなブックマークに追加 Clip to Evernote
== 演算子をオーバーロードしたら、

if ( data == null )

という箇所で、エラーとなりました。ちょっと考えれば、あたり前のことなのですが、一瞬「なぜ」と思ってしまいました。
.NET Framework のドキュメントを読むと、参照型でのオーバーロードはやらないほうが良い、というニュアンスのことが書かれていますし、やはり、参照型に対して、== をオーバーロードしないほうが良いのかな。

確かに、参照型で、== をオーバーロードしてしまうと、同一インスタンスを指しているかを調べられなくなりますからね。

まあ、このクラスは、もともと値型(構造体)の方がふさわしいのですが、Boxing,UnBoxing されるのがイヤだったので、参照型(クラス)で定義しました。
NullObject を導入して、

if ( data is MyNullData )

と書くようにしようかとも思ったのですが、うーーん、やっぱり、== はオーバーロードしないほうが良さそうです。ということで、== をオーバーロードするのは止めました。
  
Posted by gushwell at 20:07Comments(0)TrackBack(0)

2005年02月22日

ミニ言語(2)

   このエントリーをはてなブックマークに追加 Clip to Evernote
ミニ言語がなんとか動き始めました。ちょっと感動ものですね。構文ツリーをVisitorパターンを使ってたどりながら、実行するインタープリターです。P−CODEのようなオブジェクトを吐き出し、それを実行するインタープリタにしたほうが、実行速度は速くなると思われたのですが、処理速度が命の言語ではないので、パーザーが吐き出した構文ツリーをたどりながら実行する方式としました。
なお、この方式の利点は、演算子の優先順位を構文ツリーの中に埋め込めることです。BNFを書くときに優先順位を考慮した構文にしておくのですが、こうすれば、演算子の優先順位を意識することなく、構文ツリーをたどるだけで、計算が出来てしまいます。
なかなか言葉だけでは表現が難しいですね。

とにかく、デザインパターンを適用することで、思いのほか短時間で動くようになりました。
State,Compsite,Interpreter, Visiter, Iterator ,Singleton, NullObjectといったパターンを使っています。
このようなパターンを知らなかったら、きっと数倍の時間がかかっていたと思います。まだまだ完成にはほど遠いですが、先が見えました。  
Posted by gushwell at 22:15Comments(0)TrackBack(0)

2005年02月17日

ミニ言語

   このエントリーをはてなブックマークに追加 Clip to Evernote
C#でミニ言語(インタプリタ)を実装しようとしています。ミニ言語といえば、ニクラス・ヴィルトのPL/0が有名ですね。PL/0をgoogleで検索し、参考になりそうなWebページがないか調べてみました。ソースコードを公開されている方もいたようですが、さすがにC#版はなさそうです。ということで、すべて自作するという道を選びました。
まずはInterpreterパターンを使って、構文解析するところを作成。代入文、if文、while文、関数くらいしか無い、本当に小さな言語ですが、思いのほか Expression 部分が複雑になりそうです。BNF を書いたらこの部分が結構な分量でした。まあ、BNFがかければ後は、機械的にクラスわけしてコーディングするだけです。
実行部分は、Commandパターンと、この前勉強した Visitorパターンと が使えそうです。
  
Posted by gushwell at 22:35Comments(0)TrackBack(0)

2005年02月16日

NullObject

   このエントリーをはてなブックマークに追加 Clip to Evernote
NullObject を導入したら、
while ( (tok = lex.NextToken()) != null ) {
...
}

という箇所が
while ( !((tok = lex.NextToken()) is NullToken) ) {
...
}
となってしまった。うーーん、読み難いですね。
「それは、IEnumerable を実装して、foreach を使えるようにすれば、
いいんじゃないの」と誰かから言われそうですが、今は面倒なのでパス。
while ( (tok = lex.NextToken()) isnot NullToken ) {
...
}
とでも書ければ良いのだけれど...
  
Posted by gushwell at 22:15Comments(0)TrackBack(0)

2005年02月15日

集合

   このエントリーをはてなブックマークに追加 Clip to Evernote
C#には、言語で集合という概念をサポートしていません。というかほとんどの言語では、集合をサポートしていないのだと思いますが、集合の概念を簡単にコードにできないので、面倒だなーと感じることがあります。
数年前の僕だったら、ビット演算を使っっていると思いますが、どうもオブジェクト指向ぽくありません。C#では[FlagsAttribute] 属性と enumを組み合わせることで、それらしいことができるので、たいていは、[FlagsAttribute] を使っていますが、どうも、すっきりとしないときもあります。
やはり、集合クラスを自作したほうが良いのかな。
なんて、悩んでいる間にコードを書けばいいのですが...  
Posted by gushwell at 22:47Comments(2)TrackBack(0)

2005年02月13日

Visitor パターン

   このエントリーをはてなブックマークに追加 Clip to Evernote
Visitorパターンを勉強しましが。他のパターンに比べ、Visitorパターンは難しいですね。ダブルディスパッチは直感的にわかりずらいので、理解するまで、時間が掛かってしまいました。僕のような頭の悪い人間は、実際に動かして確かめるまで、なぜ、Treeをたどれるのかが複雑でわかりませんでした。
普通に再帰処理でたどるほうが僕には分かりやすいです。
でも、いろいろ考えて、なるほど、Visitorパターンが有効だということが少しづつわかってきました。
オブジェクト指向的に考えれば、ある機能というのは、そのデータと一緒にカプセル化するのが普通ですが、機能の追加が頻繁に発生することを考えると、データを保持しているクラスに機能を追加してしまうと、メンテナンスが大変になってしまいます。
Visitorパターンは、そういった時に力を発揮しそうです。
一方、機能よりもクラスの数が増えるほうが頻繁にあるとすると、メンテナンスはそれほど楽ではありませんね。

どちらにせよ、通常の再帰処理の他に、Treeをたどる方法を習得できたということは、とても大きな収穫でした。  
Posted by gushwell at 22:26Comments(0)TrackBack(0)

2005年02月09日

ListBox

   このエントリーをはてなブックマークに追加 Clip to Evernote
ListBoxに文字列をAddして行くときに、自動でスクロールしてほしい時が時々あります。
例えば、表示領域が10行分だったとして、11行目以降を Add した場合には、自動でスクロールしてくれないと、ちょっと寂しい思いをする時があります。最後にAddした文字列が、見える状態になっていてほしいということですね。
これを自動で制御してくれるプロパティが有ればいいんだけど、どうも無い見たいです。

これを実現するには、TopIndexプロパティを使い、最初に表示される項目のインデックスを設定すればOKです。
listBox1.Items.Add(s);
if ( listBox1.Height < listBox1.PreferredHeight ) {
listBox1.TopIndex =
listBox1.Items.Count - listBox1.Height/listBox1.ItemHeight;
}

まあ、上のように書けば良いのですが、実は、この if 文は不要です。
この if 文が無いと、TopIndex にマイナスの値が設定されてしまう可能性がありますが、TopIndexは、マイナス値が設定されると、無視してくれます。
ただ、これは、明確に、.NET Framework のHELP記載されているわけではありません。

ListBoxを実装する側の立場だと、例外を発生させることも出来るわけですが、そうしていないのは、プログラマの利便性を考えているからなのでしょう。そう考えると、if 文は不要という結論になりますが、一方、いやいや、ドキュメントに明確に書かれていない仕様を前提にプログラムを作ってはいけないという、鉄則もまた真なりということで、if 文を書いた方がよいのか、書かなくてもよいのか、というつまらないことで、悩んでしまいます。
  
Posted by gushwell at 21:15Comments(0)TrackBack(0)