|
Boost : |
From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-16 10:19:23
On Mon, Feb 16, 2004 at 09:19:07PM +0900, Darren Cook wrote:
> Hi,
> I've read the lambda sections of the FC++ docs, and the paper on the
> subject, and am a bit confused how to use it. Could you show the FC++
> equivalents of these BLL examples:
Sure.
I'm including just bits of commentary and code snippets in reply to
each example, and then I have also attached a full program which
demonstrates all this.
> 1. (from the paper)
> int a[]={5,3,8,4};
> std::for_each(a,a+4,std::cout<<_1<<"\n");
In FC++ it'd look like this:
std::for_each(a,a+4,
lambda(X)[ &cout %out_stream% X %out_stream% '\n' ] );
"out_stream" is the FC++ named functoid which refers to the << operator.
Unlike the real operator, it takes a stream _pointer_ as the left-hand
argument (because FC++ uses value semantics, and thus references are
icky).
The %s are FC++'s lambda infix syntax; recall that for any FC++ functoid
f, you can say
f(x,y) or x ^f^ y
to call f "now" with args x and y, or you can say
f[x,y] or x %f% y
to do the same thing inside lambda to delay evaluation and turn the call
into a lambda expression.
> 2.
> int a[]={5,3,8,4};
> std::for_each(a,a+4,std::cout<<constant("v=")<<_1<<"\n");
std::for_each(a,a+4,
lambda(X)[ &cout %out_stream% string("v=")
%out_stream% X %out_stream% '\n' ] );
Same thing here, with the added annoyance that you have to manually turn
the string literal into some "by-value" type (rather than the "array of
char const" type the darn templates deduce--ugh). The %s (rather than ^s)
ensure that evaluation happens "later", serving the same purpose as
boost::lambda's constant().
> 3. (a vector of MyClass pointers)
> std::for_each(
> tests.begin(),
> tests.end(),
> bind(&MyClass::save,_1,f)
> );
Here you would probably do
std::for_each( tests.begin(), tests.end(),
ptr_to_fun(&MyClass::save)(_,5) );
assuming that "save" is a normal method. ptr_to_fun() converts a C++
function pointer into an FC++ functoid (with an extra "this" parameter
for member functions). Here we use the short for for partial
application:
f(_,5)
which means the same as
lambda(X)[ f[X,5] ]
Note that if "save" were defined by MyClass as a functoid, things get
even easier in the client code; see the attached example (and YourClass)
for details.
> 4.
> std::for_each(
> tests.begin(),
> tests.end(),
> bind(delete_ptr(), _1)
> );
In FC++ we have a functoid called "delete_":
std::for_each( tests.begin(), tests.end(), delete_ );
> 5. (in a spirit parser)
> Node= +(
> (+range_p('A','Z'))[bind(&MyClass::on_name, this, _1,_2)]
> >> +(
> ch_p('[')
> >> (*(anychar_p-']'))[bind(&MyClass::on_value, this, _1,_2)]
> >> ch_p(']')
> )
> );
I didn't do these examples (seemed to require too much extra context),
but the gist of it would again be that
bind(&MyClass::on_name, this, _1,_2)
would be spelled
ptr_to_fun(&MyClass::on_name)(this)
// or, equivalently
// ptr_to_fun(&MyClass::on_name)(this,_,_)
in FC++ if "on_name" is a plain method, or
MyClass::on_name(this)
if it were a functoid.
See the attached program for more detail if you like, and please ask
more questions if you have them.
Brian
-- -Brian McNamara (lorgon_at_[hidden])
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk