bindの定義

いつも使うときに混乱するbind等の定義を試みた

定数

  • 1 <= N && N <= 3
  • 1 <= M && M <= 9

bind

ヘッダ
記法
  • _apply(x)を以下のように定義する
    • もしxがlambda_functorオブジェクトならば、xそのものを返す
    • そうでないならば、_always(x)を返す
      • ここで、_always(x)は常にxを返す関数オブジェクトである
有効な式
有効な式 意味
bind(f, e1,...,eM) lambda_functorオブジェクト
bind(f, e1,...,eM)(a1,...,aN) _apply(f)(a1,...,aN)(_apply(e1)(a1,...,aN),...,_apply(eM)(a1,...,aN))
前提条件
  • fはここに従って作られた関数オブジェクトである

placeholder

ヘッダ
有効な式
有効な式 意味
_I lambda_functorオブジェクト
_I(a1,...,aN) aI
前提条件
  • 1 <= I && I <= 3
  • I <= N

protect

ヘッダ
有効な式
有効な式 意味
protect(g) lambda_functorオブジェクト
protect(g)(a1,...,aN) g
前提条件
  • gはlambda_functorオブジェクトである

#include <pstade/egg/lambda/bind.hpp>
#include <boost/lambda/core.hpp>
#include <boost/lambda/lambda.hpp>
#include <pstade/minimal_test.hpp>

struct T_foo
{
    typedef int result_type;

    int operator()(int i, int j, int k) const
    {
        return i + j * k;
    }
};

T_foo const foo = {};


void pstade_minimal_test()
{
    int ignored = 0;

    // lvalues for Boost1.34.
    int _10 = 10;
    int _20 = 20;
    int _30 = 30;

    BOOST_CHECK( bll::_1 (_10) == 10 );
    BOOST_CHECK( bll::_1 (_10, ignored) == 10 );
    BOOST_CHECK( bll::_1 (_10, ignored, ignored) == 10 );

    BOOST_CHECK( bll::protect(bll::_1)(ignored) (_20) == 20 );
    BOOST_CHECK( bll::protect(bll::_1)(ignored) (_30, ignored, ignored) == 30 );

    // lambda_bindはboost::lambda::bindの関数オブジェクト版
    // これはlambda_functorオブジェクトではない
    egg::T_lambda_bind const bind = egg::lambda_bind;

    // \x -> (\y -> foo(x, y, 30))
    BOOST_CHECK( 10+20*30 ==
        bind(bind, foo, bll::_1, bll::protect(bll::_1), 30) (_10)(_20)
    );
    /*
        bind(bind, foo, bll::_1, bll::protect(bll::_1), 30) (_10)(_20);
        = bind(_apply(foo)(_10), _apply(bll::_1)(_10), _apply(bll::protect(bll::_1))(_10), _apply(30)(10)) (_20);
        = bind(foo, bll::_1(_10), bll::protect(bll::_1)(_10), 30) (_20);
        = bind(foo, _10, bll::_1, 30) (_20);
        = foo(_apply(_10)(_20), _apply(bll::_1)(_20), _apply(30)(_20));
        = foo(_10, bll::_1(_20), 30);
        = foo(_10, _20, 30);
    */

    // \x -> (\y,z -> foo(x, y, z))
    BOOST_CHECK( 10+20*30 ==
        bind(bind, foo, bll::_1, bll::protect(bll::_1), bll::protect(bll::_2))
            (_10)(_20, _30)
    );

    // \x -> (\y -> (\z -> foo(x, y, z)))
    BOOST_CHECK( 10+20*30 ==
        bind(bind, bind, foo, bll::_1, bll::protect(bll::_1), bll::protect(bll::protect(bll::_1)))
            (_10)(_20)(_30)
    );
}