Presentation is loading. Please wait.

Presentation is loading. Please wait.

2/26/2016 1 Customization Points and Polymorphism Functional Programming Boost.Lambda.

Similar presentations


Presentation on theme: "2/26/2016 1 Customization Points and Polymorphism Functional Programming Boost.Lambda."— Presentation transcript:

1 2/26/2016 1 Customization Points and Polymorphism Functional Programming Boost.Lambda

2 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 2 Functional Programming A paradigm for computing with functions  Not Procedural/Imperative Based on Lambda Calculus Avoids data mutation Often, resulting code is Concise (terse) Efficient (inlining, static dispatch, return val. opt.) Robust (multithreading, no side effects) Alonzo Church

3 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 3 Lambda Calculus In-line anonymous function definition  λ(x, y).x+y  λ(x, y) { return x + y; } Typing  template R λ(X & x, Y & y) { return x + y; }  Return value type deduction is hard!

4 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 4 STL and the Functional Paradigm Remember this? ProsCons Efficient  Hard to write Idiomatic  Hard to read // For each int i in s, print i * 3: std::transform( s.begin(), s.end(), std::ostream_iterator (std::cout, " "), std::bind2nd(std::multiplies (), 3) );

5 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 5 Lambda Functions Using Boost.Lambda // For each int i in s, print i * 3: std::for_each( s.begin(), s.end(), std::cout << ( _1 * 3 ) << " " ); Boost.Lambda helps STL deliver on the promises of Functional Programming

6 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 6 Lambda in C++ std::cout << ( _1 * 3 ) << " “  λ (_1) { std::cout << _1 * 3 << “ ”; } _1 + _2  λ (_1, _2) { return _1 + _2; } Evaluation  int x = 10, y = 20;  (_1 + _2) (x, y);  Gotcha: (++_1) (10); cannot take non-const r-values Plus node Placeholder _1 Placeholder _2

7 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 7 Higher-Order Functions Higher-order Function  A function that takes a function as an argument, and/or returns a function. Currying  Binding a function to some of its arguments.  Example, using Boost.Bind boost::bind(std::plus (), 42, _1)  (int, int)  int  (int)  int std::tr1::

8 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 8 Bind Pseudocode int λ (int & x) { return std::plus () (42, x); }

9 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 9 Binding Member Functions Resize all strings in a vector :  with STL binders:  with Boost.Bind: std::for_each( s.begin(), s.end(), std::bind2nd( std::mem_fun_ref( &std::string::resize ), 2 ) ); std::for_each( s.begin(), s.end(), boost::bind( &std::string::resize, _1, 2 ) ); With member function, boost::bind (&std::string::resize, _1, _2) the first argument is always “*this” : _1->resize (_2);

10 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 10 Nested Binds Total risk calculation: With function pointer With Boost.Bind: std::accumulate( loans.begin(), loans.end(), 0.0f, bind( std::plus (), _1, bind( &loan::risk, _2, years ) ) ); float total = 0.0f; for (int i = 0; i < loans.size(); ++i) total += loans[i]->risk(years); float addRisk (float riskSoFar, Loan * loan) { return riskSoFar + loan->risk (years); // years global } std::accumulate (loans.begin(), loans.end(), 0.0f, addRisk);

11 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 11 Nested Binds, cont. With Boost.Lambda:  No need for std::plus (return type deduction) Magic:  the meaning of _2 in bind makes sense only in the context of the outer expression  Warning: not always what one wants! using namespace boost::lambda; std::accumulate( loans.begin(), loans.end(), 0.0f, _1 + bind( &loan::risk, _2, years ) ) );

12 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 12 Bind and Relational Operators Find a pair for which p.second == 42 std::vector > v; std::find_if( v.begin(), v.end(), 42 == std::tr1::bind( &std::pair ::second, _1 ) ); What is special about the relational operators that lets Boost.Bind horn in on Boost.Lambda’s territory like this?

13 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 13 Introducing Boost.Function Dynamically polymorphic function object Usage: boost::function Wraps anything callable that accepts A1, A2, … A n and whose result can be converted to R For example: typedef boost::function func; func f0( &std::min );// function pointer func f1( std::less () );// function object func f2( std::less () ); Templated implicit conversion erases type automagically!

14 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 14 Bind and Boost.Function Problem: how to save a curried function? Boost.Function can also save Lambdas! boost::function add42 = bind( std::plus (), 42, _1 ); cout << add42( 1 ) << endl; // prints "43" ??????????????????????? boost::_bi::bind_t< boost::_bi::unspecified, std::plus, boost::_bi::list2, boost::arg > > add42 = 42 + boost::lambda::_1; cout << add42( 2 ) << endl; // prints "44"

15 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 15 Other uses for Boost.Function Decoupling components  powerful and stable APIs Generic callbacks, eg.:  Boost.Threads  Boost.Signals Ad hoc polymorphism The benefits of OO without the goop

16 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 16 Lambda and Member Syntax bind() syntax isn’t always ideal Wouldn’t this be better? int sum_second( vector * > const & v ) { return std::accumulate( v.begin(), v.end(), 0, _1 + bind( &pair ::second, _2 ) ); } int sum_second( vector * > const & v ) { return std::accumulate( v.begin(), v.end(), 0, _1 + _2 -> second ) } // SYNTAX ERROR! int sum_second( vector * > const & v ) { return std::accumulate( v.begin(), v.end(), 0, _1 + _2 ->* &pair ::second ); // OK! }

17 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 17 A Lambda Gotcha! What’s wrong with this? Deferring evaluation void display_ints( vector const & v ) { std::for_each( v.begin(), v.end(), std::cout << '+' << _1 ); } Displays: "+1234" void display_ints( vector const & v ) { std::for_each( v.begin(), v.end(), std::cout << constant('+') << _1 ); } Displays: "+1+2+3+4"

18 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 18 Assignment in Lambdas Closure  A function bound to a lexical scope  C++ doesn’t have them  Achieving closure with Boost.Lambda template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, i = i + 1 ); return i; } Error! Not a lambda! template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, i = i + constant(1) ); return i; } Error! Can’t assign lambda to int! template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, var(i) = i + constant(1) ); return i; } Wrong! Evaluates as "i = 0 + 1" template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, var(i) = var(i) + 1 ); return i; } OK! template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, ++var(i) ); return i; } Also, OK! template int LL_distance( It begin, It end ) { int i = 0; std::for_each( begin, end, i += constant(1) ); return i; } Also, OK!

19 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 19 Advanced Lambdas A Boost.Lambda for loop: Some other Boost.Lambda control structures:  if_(condition)[then_part]  if_(condition)[then_part].else_[else_part]  while_(condition)[body]  do_[body].while_(condition) int a[5][10]; int i; std::for_each( a, a+5, for_( var(i) = 0, var(i) < 10, ++var(i) ) [ _1[ var(i) ] += 1 ] ); Initialization Condition Increment Loop body

20 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 20 Guarding Against Nested Binds // F is a unary function template void nested( const F & f ) { int x;... bind( f, _1 )(x); } // bar is a binary function int bar( int, int ); // Curry bar into unary function nested( bind( bar, 1, _1 ) ); bind (bind(bar, 1, _1), _1) (x); Oops! “f” is a nested bind! // F is a unary function template void nested( const F & f ) { int x;... bind( unlambda(f), _1 )(x); } unlambda() ensures that a function object that happens to be a bind() is not treated magically.

21 copyright 2006 David Abrahams, Eric Niebler 2/26/2016 21 In a Bind Think functional Use Boost.Bind for currying and simple predicates Use Boost.Lambda when you want infix operators and control structures Use Boost.Function to store Binds and Lambdas and define powerful APIs Bind and Function are coming soon to a standard library near you!


Download ppt "2/26/2016 1 Customization Points and Polymorphism Functional Programming Boost.Lambda."

Similar presentations


Ads by Google