210 likes | 359 Views
Funcadelic. NKU CSC 601 Fall 2002 K. Kirby. Functionals & Function Objects for. Composition (the wrong way, the right way) C-function-pointer to function object adapter Binder (currying adaptor). f. g. Composition. (define compose (lambda (f g) (lambda (x) (f (g x)))))
E N D
Funcadelic NKU CSC 601 Fall 2002 K. Kirby
Functionals & Function Objects for... • Composition (the wrong way, the right way) • C-function-pointer to function object adapter • Binder (currying adaptor)
f g Composition (define compose (lambda (f g) (lambda (x) (f (g x))))) ((compose sqrt to-real) "2") (map (compose abs sin) sequence)
Composition double x= sqrt( atof( "2" ) ) ; // 1.414 double y= (compose( ptr_fun( sqrt ), ptr_fun( atof )))( "2" ) ; // 1.414
Composition: Use with Algorithms double xar[N], yar[N] ; generate( xar, xar+N, rand ) ; // Compute |sin x| for every x in xar[]. transform( xar, xar+N, yar, compose( ptr_fun( fabs ), ptr_fun( sin ) ) ) ;
Possibilities? ? unary_function<double,string> h= compose( ptr_fun( sqrt ), ptr_fun( atof )) ; ?? unary_function<double,string>* ph= & compose( ptr_fun( sqrt ), ptr_fun( atof )) ; ??? composition<double,double,string> h= compose( ptr_fun( sqrt ), ptr_fun( atof )) ; No no no.
f g h An attempt: the functional template< typename TOut, typename TMid, typename TIn > unary_function<TOut,TIn> compose( unary_function<TOut,TMid> f, unary_function<TMid,TOut> g ) // // Create a composition (lambda x) (f(g(x)) // { Composition<TOut,TMid,TIn> h( f, g ) ; return h ; }
f g An attempt: the functional template< typename TOut, typename TMid, typename TIn > unary_function<TOut,TIn> compose( unary_function<TOut,TMid> f, unary_function<TMid,TOut> g ) // // Create a composition (lambda x) (f(g(x)) // { return Composition<TOut,TMid,TIn>( f, g ) ; }
g f An attempt: the function object template< typename TOut, typename TMid, typename TIn > class Composition : public unary_function< TIn, TOut > { public: Composition( const unary_function< TMid, TOut >& f, const unary_function< TIn, TMid >& g ) : _f(f) , _g(g) {} TOut operator()( TIn x ) { return _f( _g( x ) ) ; } private: unary_function< TMid, TOut > _f ; unary_function< TIn, TMid > _g ; } ; NO
f g The right way: the functional template< typename UnFun1, typename UnFun2 > Composition<UnFun1,UnFun2> compose( const UnFun1& f, const UnFun2& g ) // // Create a composition (lambda x) (f(g(x))) // { return Composition<UnFun1,UnFun2>( f, g ) ; }
g f The right way: the function object template< typename UnFun1, typename UnFun2 > class Composition : public unary_function< typename UnFun2::argument_type, typename UnFun1::result_type > { public: Composition( const UnFun1& f, const UnFun2& g ) : _f(f) , _g(g) {} typename UnFun1::result_type operator()( typename UnFun2::argument_type x ) { return _f( _g ( x ) ) ; } private: UnFun1 _f ; UnFun2 _g ; } ;
f Adapters: a functional template <typename TArg,typename TArg2, typename TArg3, typename TRes> TerFunAdapter<TArg,TArg2,TArg3,TRes> ptr_fun( TRes (*f)(TArg,TArg2,TArg3) ) // // A functor that takes a 3-arg function and returns the corresponding // ternary function object. // { return TerFunAdapter<TArg,TArg2,TArg3,TRes>( f ) ; }
f Adapters: a function object template <typename TArg1, typename TArg2, typename TArg3, typename TRes> class TerFunAdapter: public ternary_function< TArg1, TArg2, TArg3, TRes > { public: TerFunAdapter( TRes (*f)(TArg1,TArg2,TArg3) ) // Constructor stores the function for later invocation. : _f(f) { } TRes operator()( const TArg1& arg1, const TArg2& arg2, const TArg3& arg3 ) const // Relays a call on this function object to a call on the underlying function. { return _f( arg1, arg2, arg3 ) ; } private: TRes (*_f( TArg1,TArg2,TArg3 ) ; } ;
Currying adapters (binders): a functional template <class TerFn, typename T> binder3rd<TerFn> bind3rd( const TerFn& f, const T& arg3 ) // Constructs and returns a Binder3rd object from this ternary function object and argument. { return binder3rd< TerFn >( f, arg3 ) ; } f arg3
_f Binders: a function object _arg3 template <class TerFn> class binder3rd : public binary_function< typename TerFn::first_argument_type, typename TerFn::second_argument_type, typename TerFn::result_type > { public: binder3rd( const TerFn& f, const typename TerFn::third_argument_type arg3 ) // Constructs this binary function object by storing a ternary function object and the frozen 3rd arg. : _f(f), _arg3( arg3 ) { } typename TerFn::result_type operator() ( const typename TerFn::first_argument_type& arg1, const typename TerFn::second_argument_type& arg2 ) const // Translates the binary call to the ternary call with the stored 3rd argument. { return _f( arg1, arg2, _arg3 ) ; } private: TerFn _f ; // the underlying ternary function object typename TerFn::third_argument_type _arg3 ; // the frozen third argument } ;
A little ternary function object template <typename TNum> struct SumIs : public ternary_function<TNum,TNum,TNum,bool> { bool operator()( const TNum& n1, const TNum& n2, const TNum& sum ) const { return n1 + n2 == sum ; } } ;
Count the number of corresponding terms in these two sequences (*first1,...) (*first2,...) that satisfy the binary predicate pred2. // 20th Century Style template <typename Iter1, typename Iter2, typename Pred2> int count_match_if( Iter1 first1, Iter1 last1, Iter2 first2, Pred2 pred2 ) { int count= 0 ; while ( first1 != last1 ) if ( pred2( *first1++, *first2++ ) ) count++ ; return count ; } // 21st Century Style?? template <typename Iter1, typename Iter2, typename Pred2> int count_match_if( Iter1 first1, Iter1 last1, Iter2 first2, Pred2 pred2 ) { return inner_product( first1, last1, first2, 0, plus<int>(), pred2 ) ; }
Count the number of positions in a pair of sequences where the corresponding elements to not add up to n. count_match_if( ls.begin(), ls.end(), ar, not2( bind3rd( SumIs<int>(), n ) ) ) ;
struct Point { Point( double x =0, double y =0) : x(x), y(y) {} ; void translate( double dx, double dy ) { x += dx ; y += dy ; } void scale( double factor ) { x*= factor ; y*= factor ; } double getMagnitude() const { return sqrt( x*x + y*y ) ; } void print() const { cout << "(" << x << "," << y << ") " ; } ; double x, y ; } ; vector<Point> vpts(n) ; // ... for_each( vpts.begin(), vpts.end(), mem_fun_ref( Point::print ) ) ;