bind.d

Boost.bind の D 版を作ってみました。めんどいだけであまり実装とか面白くもなかったというか、メソッドテンプレートが無いので opCall(...) を実行時に解決するというダサい解になっています。一応型チェックはそれなりにしてあるはず。

http://shinh.skr.jp/d/bind.tgz

ユニットテスト節から適当に使用例を引用。

    int func(int i, int j) { return i*2 + j; }
    auto f = bind(&func, _1, _2);
    static assert(is(f.calltype == Tuple!(int, int)));
    assert(f(1, 2) == 4);

    auto f2 = bind(&func, _2, _1);
    static assert(is(f2.calltype == Tuple!(int, int)));
    assert(f2(1, 2) == 5);

    auto f3 = bind(&func, _1, _1);
    static assert(is(f3.calltype == Tuple!(int)));
    assert(f3(1) == 3);

    char func2(int i, char[] msg) { return msg[i]; }

    auto f4 = bind(&func2, _2, _1);
    static assert(is(f4.calltype == Tuple!(char[], int)));
    assert(f4("abc", 1) == 'b');

    char[] abcdef = "abcdef";

    auto f5 = bind(&func2, _1, abcdef);
    static assert(is(f5.calltype == Tuple!(int)));
    assert(f5(1) == 'b');

    auto f6 = bind(&func2, 1, _1);
    static assert(is(f6.calltype == Tuple!(char[])));
    assert(f6("abcd") == 'b');

    char[] func3(int i, int j, char[] msg) { return msg[i..j]; }
    auto f7 = bind(&func3, _2, _1, abcdef);
    static assert(is(f7.calltype == Tuple!(int, int)));
    assert(f7(2, 1) == "b");

    void func_types(int i, float f, char c, bool b, char[] s) {
        assert(i == 1);
        assert(f == 2.0);
        assert(c == 'a');
        assert(b);
        assert(s == "hoge");
    }

    char[] hoge = "hoge";

    auto ft0 = bind(&func_types, 1, 2.0, _1, true, hoge);
    static assert(is(ft0.calltype == Tuple!(char)));
    ft0('a');
/*
    auto ft1 = bind(&func_types, _4, _3, _2, true, _1);
    static assert(is(ft1.calltype == Tuple!(char[], char, float, int)));
    ft1("hoge", 'a', 2.0, 1);

    auto ft2 = bind(&func_types, _2, _3, 'a', true, _1);
    static assert(is(ft2.calltype == Tuple!(char[], int, float)));
    ft2("hoge", 1, 2.0);
*/
version(Windows) {
    auto ft3 = bind(&func_types, _1, 2.0, 'a', true, _2);
    static assert(is(ft3.calltype == Tuple!(int, char[])));
    ft3(1, "hoge");
}

コメントアウトしてある部分はなぜか assert で落ちるのでコメントアウトしました。 Linux だとコンパイラが落ちるのでコンパイラのバグかなーと思いますがよくわかりません。同じく version(Windows) 内も Linux ではコンパイラが落ちます。

あとシンボルの長さが1000文字程度で怒られるようなので、 30引数まで対応してあるものの、実際のところは 10引数程度が限度かもしれません。

あと opCall(...) なので bind を bind できないという問題もあります。まぁ色々やる気が失せてきたのでこんなもんで。

あと Linux でリンク時に謎 warning が出るのもよくわからない。

そういえば実装しようと思ったのは

http://d.hatena.ne.jp/niha/20060612#1150120289

の curry とか見て、なのですが、なんというか関数型言語の flip って気持ち悪くないですか、という話が。

なにかあれば下記メールアドレスへ。
shinichiro.hamaji _at_ gmail.com
shinichiro.h