Download Boost.Lambda

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

C Sharp (programming language) wikipedia , lookup

Functional programming wikipedia , lookup

APL syntax and symbols wikipedia , lookup

C++ wikipedia , lookup

Standard ML wikipedia , lookup

C syntax wikipedia , lookup

Transcript
Customization Points and
Polymorphism
Functional Programming
Boost.Lambda
5/9/2017
1
Functional Programming

A paradigm for computing
with functions
 Not
Procedural/Imperative
Based on Lambda Calculus
 Avoids data mutation
 Often, resulting code is

Alonzo Church
 Concise (terse)
 Efficient (inlining, static dispatch, return val. opt.)
 Robust (multithreading, no side effects)
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
2
Lambda Calculus


In-line anonymous function definition
 λ(x,
y).x+y
 λ(x,
y) { return x + y; }
Typing
 template<class
X, class Y, class R>
R λ(X & x, Y & y) { return x + y; }
 Return value type deduction is hard!
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
3
STL and the Functional Paradigm

Remember this?
// For each int i in s, print i * 3:
std::transform(
s.begin(), s.end(), std::ostream_iterator<int>(std::cout, " "),
std::bind2nd(std::multiplies<int>(), 3) );
Pros
Efficient
Idiomatic
5/9/2017
Cons
Hard to write
Hard to read
copyright 2006 David Abrahams, Eric Niebler
4
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
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
5
Lambda in C++

std::cout << ( _1 * 3 ) << " “
λ

_1 + _2
λ

(_1) { std::cout << _1 * 3 << “ ”; }
(_1, _2) { return _1 + _2; }
Evaluation
 int
x = 10, y = 20;
Plus node
 (_1 + _2) (x, y);
Placeholder _1
Placeholder _2
 Gotcha:
(++_1) (10);
cannot take non-const r-values
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
6
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
std::tr1::
boost::bind(std::plus<int>(), 42, _1)
(int)

intint
(int,
int)
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
7
Bind

Pseudocode
int λ (int & x) { return std::plus<int>() (42, x); }
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
8
Binding Member Functions
Resize all strings in a vector<string>:
 with
STL binders:
std::for_each( s.begin(), s.end(),
std::bind2nd( std::mem_fun_ref( &std::string::resize ), 2 ) );
 with
Boost.Bind:
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);
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
9
Nested Binds

Total risk calculation:
float total = 0.0f;
for (int i = 0; i < loans.size(); ++i)
total += loans[i]->risk(years);

With function pointer
float addRisk (float riskSoFar, Loan * loan)
{
return riskSoFar + loan->risk (years); // years global
}
std::accumulate (loans.begin(), loans.end(), 0.0f, addRisk);

With Boost.Bind:
std::accumulate( loans.begin(), loans.end(), 0.0f,
bind( std::plus<float>(), _1, bind( &loan::risk, _2, years ) ) );
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
10
Nested Binds, cont.

With Boost.Lambda:
using namespace boost::lambda;
std::accumulate( loans.begin(), loans.end(), 0.0f,
_1 + bind( &loan::risk, _2, years ) ) );
 No
need for std::plus<float> (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!
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
11
Bind and Relational Operators

Find a pair for which p.second == 42
std::vector< std::pair<int, int> > v;
std::find_if( v.begin(), v.end(),
42 == std::tr1::bind( &std::pair<int, int>::second, _1 ) );
What is special about the relational
operators that lets Boost.Bind horn in on
Boost.Lambda’s territory like this?
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
12
Introducing Boost.Function

Dynamically polymorphic function object

Usage:

Wraps anything callable that accepts A1, A2, … An and
whose result can be converted to R

For example:
boost::function< R ( A1, A2, … An ) >
typedef boost::function<int (int, int)> func;
func f0( &std::min<int> );
// function pointer
func f1( std::less<int>() ); // function object
func f2( std::less<long>() );

Templated implicit conversion erases type automagically!
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
13
Bind and Boost.Function

Problem: how to save a curried function?
??????????????????????? add42 = bind( std::plus<int>(), 42, _1 );
boost::function<int(int)>
cout << add42( 1 ) << endl; // prints "43"
boost::_bi::bind_t<
boost::_bi::unspecified
, std::plus<int>
, boost::_bi::list2<boost::_bi::value<int>
 Boost.Function can
also save
, boost::arg<1>
> > Lambdas!
add42 = 42 + boost::lambda::_1;
cout << add42( 2 ) << endl; // prints "44"
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
14
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
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
15
Lambda and Member Syntax

bind() syntax isn’t always ideal
int sum_second( vector< pair<int,int> * > const & v ) {
return std::accumulate( v.begin(), v.end(), 0,
_1 + bind( &pair<int,int>::second, _2 ) );
}

Wouldn’t this be better?
int sum_second( vector< pair<int,int> * > const & v ) {
return std::accumulate( v.begin(), v.end(), 0,
-> second
)
_1 + _2 ->*
&pair<int,int>::second
// SYNTAX ERROR!
); // OK!
}
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
16
A Lambda Gotcha!

What’s wrong with this?
void display_ints( vector< int > const & v ) {
std::for_each( v.begin(), v.end(),
std::cout << '+' << _1 );
Displays: "+1234"
}

Deferring evaluation
void display_ints( vector< int > const & v ) {
std::for_each( v.begin(), v.end(),
std::cout << constant('+') << _1 ); Displays: "+1+2+3+4"
}
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
17
Assignment in Lambdas

Closure
A
function bound to a lexical scope
 C++ doesn’t have them 

Achieving closure with Boost.Lambda
template< class It >
int LL_distance( It begin, It end ) {
int i = 0;
1var(i)
std::for_each( begin, end, i++var(i)
var(i)
=i+
+=
constant(1)
=constant(1)
i );
);
+ constant(1)
+ 1););); );
return i;
Error!
Not
aOK!
lambda!
Wrong!
Also,
Can’t
Evaluates
assign
OK!
as
lambda
"i = 0to+ int!
1"
}
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
18
Advanced Lambdas

A Boost.Lambda for loop:
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
Some other Boost.Lambda control structures:
 if_(condition)[then_part]
 if_(condition)[then_part].else_[else_part]
 while_(condition)[body]
 do_[body].while_(condition)
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
19
Guarding Against Nested Binds
// F is a unary function
// bar is a binary function
template< class F >
int bar( int, int );
void nested( const F & f )
{
// Curry bar into unary function
int x;
nested( bind( bar, 1, _1 ) );
...
bind( f,
unlambda(f),
_1 )(x);
_1 )(x);
bind (bind(bar, 1, _1), _1) (x);
}
unlambda()
ensures that a function
Oops! “f”
is a
nestedobject
bind! that happens to be a bind() is
not treated magically.
5/9/2017
copyright 2006 David Abrahams, Eric Niebler
20
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!

5/9/2017
copyright 2006 David Abrahams, Eric Niebler
21