データと言語

 データを言語であると考えるなら、そのデータを処理するプログラムは言語のインタプリタだ。bmpは画像定義言語、ペイントは画像定義言語の処理系と考えられる。

 だいたいのプログラムは(どっかの誰かが互換性を持ったプログラムを開発しない限り)自分だけのデータ形式のデータを受け付ける。それをたとえばXMLで構成してデータ形式を丸見えにしてしまえば、他の汎用言語を使ってデータを生成することができる。プログラムが他の汎用言語のインタプリタを内臓すれば、独自形式のデータの中に生成過程を取り込めるようになる。XMLに縛られる必要もなくなる。この辺が静的型言語の苦手とするところだが、別にC#C#コンパイラを内蔵してるので簡単に使える。

 今日食べるものを決定する処理を行うコンポーネントAがある。Aの出した答えが「ご飯を3杯食べる」というものだったとする。その結果を表す方法として、(ご飯、3)というデータをただ返す方法と、メソッドを引数にもらってコールバックする方法とある。

 (ご飯、3)というデータが返った場合、そのデータをどう解釈しようとユーザーの自由だ。データを言語と考えるなら、食事言語の処理系をどのように作るかで結果は全く変わってくる。

 ご飯がただのデータでなくFoodから継承されたバーチャルメソッドを持っていたとすると、それを3回呼び出すという形で結果を適用することも出来る。それによってPersonのカロリーが300*3増えたりするわけだが、値を書き換えるバーチャルメソッドがユーザーの知らぬ間に3回呼び出されるなんてのは濃厚な死の香りしかしない。この場合素直に(ご飯,3)を返してやるのが正しいだろう。

 ボタンを押すと次の画像が表示される、という処理を考える。C#的にはbutton.Click += (sender,e) => form.NextImage();てな感じコールバックを与えるのが自然だ。これはGUIの処理手順が値を返せるようになってないためだ。普通に考えると、formがbuttonを参照し、buttonがコールバックを参照しコールバックがformを参照するという循環した構造は避けたいところだ。

 いろいろややこしいことを行い、値を返せるようになったとする。

while(true)
{
  Result r = WaitInput();
  switch(r.Action)
  {
    case Action.Next:
      form.InvokeNextImage();
      break;
    ...
  }
}

 実にキモイものになる。GUIは本当に度し難い。この場合データを返すのでなくコールバックを実行した方がいいだろう。

 これが相互参照してしまうのはどうしようもないと思うが、button.Click += (...)=>{model.NextImage(); form.Update(model);}こんな風にしてやれば依存関係が抑えられる。modelをデータとしてformはそれを解釈するインタプリタにするという形だ。