++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

C# でダックタイプインターフェース その2

leave a comment »

一昨日書いた、ダックタイプインターフェースの話、ちょっと更新。

StracturalSubtyping.zip

  • Shape.cs : 一昨日書いた奴をちょっと更新
    • 作った仮想メソッドテーブルをキャッシュするようにした
    • エラー処理をちょっと追加
  • IntegerSet.cs : 同じ仕組みで多重ディスパッチしたくて作ったもの

後者に関してちょっと説明。

ほんとにやりたいのは以下のような構文。

interface SetComparer(T, U)
{
    func (x T, y U) AreEqual() bool;
    func (x T) Contains(y U) bool;
}

var x = new Range { Min = 1, Max = 4 };
var y = new List { Values = { 1, 2, 3, 4 } };
(x, y).AreEqual();
x.Contains(y);

似たような書き方は C# ではどうあがいても無理臭いので、あきらめた結果が以下のような書き方。

interface SetComparer
{
    bool Equal();
    bool Contain();
}

var x = new Range { Min = 1, Max = 4 };
var y = new List { Values = { 1, 2, 3, 4 } };
SetComparer c = AsSetComparer(x, y);
c.Equal();
c.Contain();

以下、感想。

全般

  • ダックタイプ的なインターフェースって、Structural Subtyping って言った方がいいのかな(OCaml ではそう呼ぶらしい)

C# コードに関して

  • コード書くのが面倒だったんで、ジェネリクスとリフレクション使ってやっちゃってるけど、ほんとはコード生成で静的な AsSetComparer 書かなきゃダメかも
    • (要するに、別言語作る。別言語から C# コード生成。)
    • 実行効率の問題があるし
    • 静的型チェックができないとあんまりうれしくない
    • 一応、利用側で IntelliSense が使えるっていう利点はある
  • やってることは自前で仮想メソッドテーブル作ってるようなもの
    • どうせコード生成でいくなら、interface を継承したクラスを自動生成すること考える方がいいかも
  • 同じ仕組みで operator も扱おうとちょっと考えてみたけどめんどくさそう
    • 組み込み型の演算子と、operator オーバーロードやってるクラスを同列に扱うのが大変
    • C# 4.0 の dynamic の実装が仮想メソッドテーブルを作るんじゃなくて、if (x is T) Method((T)x); な感じの動的コード生成になってるのも納得

ほんとにやりたい方の文法に関して

  • func のところは Go っぽく書いた
  • Go を見る前から、以下のような文法な言語はどこかにないものかって考えてた
    • def x:T1, y:T2 .Method a:Arg1, b:Art2 => p:Ret1, q:Ret2 { Body }
    • Body が単文の時に限り、
      • def x:T1, y:T2 .Method a:Arg1, b:Art2 => a * x, b * y;
    • 型推論が利く状況下で、ラムダ式的に、
      • f = def x, y . a, b => a * x, b * y;
    • 呼び出し側
      • p, q = (x, y).Method(a, b);
      • あるいは、代入も右向きでいいかもなぁ
        • (x, y).Method(a, b) => p, q;
    • 上記の SetComparer 的なのを実現するために
      • def (x:Set, y:Set):SetComparer .Method => Ret;
      • 引数リスト:多重インターフェース
  • まあ、ネタ
    • (x, y).Method(a, b) って構文、面白いとは思ってるけど、実用度は低いかなぁ
      • IntelliSense の実装((x, y). って打った時点で補完候補に Method を出す)が大変になりそうな割にはメリットがあんまり
    • 多値返却メソッドと組み合わせると面白そうではあるんだけど
      • 戻り値として2値 (x, y) を返す関数に、メソッドチェーンで別のメソッドつなぐ
        • .Method1().Method2() みたいな
      • Tuple 使えって話なんでしょうが
        • Tuple<P, Q> Method(this Tuple<T, U> t)
        • C# に Tuple を簡単に書くための構文糖衣があるだけで、ここに書いたのと似たようなこと、できなくはない
        • 例: @(x, y).Method(a, b)new Tuple<T, U>(x, y).Method(a, b)

Written by ufcpp

2009年11月15日 @ 13:26

カテゴリー: C#

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。