|
Boost Users : |
From: tom gee (rockonedge_at_[hidden])
Date: 2005-09-22 21:27:27
Thanks to Simon for the elaborate explanation.
Thanks to Bjorn again for the url, getting me to the right place.
Yes, I should have gone through the docs. (*^©n^*)
> Message: 1
> Date: Thu, 22 Sep 2005 20:44:08 +1200
> From: Simon Buchan <simon_at_[hidden]>
> Subject: Re: [Boost-users] A question about boost::lambda::if_
> behavior
> To: boost-users_at_[hidden]
> Message-ID: <dgtqts$e0j$1_at_[hidden]>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
> Bjorn.Karlsson_at_[hidden] wrote:
> > Hello Tom,
> >
> > -----Original Message-----
> > From: tom gee [mailto:rockonedge_at_[hidden]]
> > Subject: [Boost-users] A question about boost::lambda::if_ behavior
> >
> >
> >>Can anyone please explain this code:
> >
> > [snip]
> >
> > The problem is that the expression std::cout << constant("Bingo:<") is
> > evaluated immediately. Why? Because it's not a lambda expression. You have
> > two options that will help you turn your if-branch into a lambda expression;
> > either use boost::lambda::var or boost::lambda::constant.
> >
> > Using boost::lambda::var:
> >
> > std::for_each(setFinalVal.begin(),setFinalVal.end(),
> > (std::cout << _1 << " ", if_(_1 < 24.000001 && _1 > 23.999999)
> > [var(std::cout) << "Bingo:<" << _1 << ">"]));
> >
> > Using boost::lambda::constant:
> >
> > std::for_each(setFinalVal.begin(),setFinalVal.end(),
> > (std::cout << _1 << " ", if_(_1 < 24.000001 && _1 > 23.999999)
> > [std::cout << constant("Bingo:<") << _1 << ">"]));
> >
> >
> > Cheers,
> > Bjorn Karlsson
> constant should be better (lower overhead, conceptually closer),
> but no biggy. I beleive this is the No.1 FAQ, is it not?
> (PS: why does not the lambda docs say in the function call overload
> section to use BLL's bind? It took me AGES to figure out how to do
> that!)
>
> Message: 7
> Date: Thu, 22 Sep 2005 22:37:28 +1200
> From: Simon Buchan <simon_at_[hidden]>
> Subject: Re: [Boost-users] A question about boost::lambda::if_
> behavior
> To: boost-users_at_[hidden]
> Message-ID: <dgu1ic$2g2$1_at_[hidden]>
> Content-Type: text/plain; charset=ISO-8859-1; format=flowed
>
> tom gee wrote:
> > Hello Bjorn,
> >
> > Thanks for such a quick help. I works now.
> >
> > Can you please further explain the usage of var and constant .
> > in the expression
> > if_(_1 < 24.000001 && _1 > 23.999999)[ cout <<"Bingo:<"<<_1<<">"])
> > I understand "Bingo:<" is evaluated immediately, why not ">", which is not a
> > lambda expression either, is not
> > evaluated along.
> >
> Refresher course: an expression like:
> cout << foo << bar << endl;
> is read (aka parsed) by the compiler to be shorthand for the following:
> (((cout << foo) << bar) << endl);
> which, incidently is just shorthand for:
> operator<<(operator<<(operator<<(cout, foo), bar), endl);
> Thus, '<<' is known as a 'left assosiative' (I think :D) operator.
> Refresher over.
> Basicly, the 'cout << "Bingo:<"' sub-expression has no 'lambda stuff' in
> it, and therefore calls the _normal_ operator<<, which immediately
> prints "Bingo:<". This operator<< returns a reference to cout, so the
> next '<<' sees:
> cout << _1
> Which (obviously) is an expression containing a lambda (sub-)expression.
> The guys who made this library were nice enough to provide overloads of
> '<<' (along with every other possible operator) that return a 'lambda
> function object', you just have to know that it is a valid lambda
> expression that _will_ evalute as "cout << _the_first_argument_" when
> called. The same happens with the next <<, it sees:
> _lambda_operator_left_shift_ << ">"
> , where the left argument is the previous lambda function object made
> from the "cout << _1" sub-expression. Now there is _another_ overload of
> << that creates _another_ lambda function object, that _will_ evalute as
> if it was:
> cout << _the_first_argument_ << ">"
> So, basicly, anytime there is a sub-expression that doesn't have a
> lambda object in it, it is treated as a normal expression, but if it
> does, it creates a function object that will do what it looks like it
> would do. What 'constant' and 'var' do is make a (lambda?) function
> object that just returns it's argument, as, respectively, a constant
> copy, or a reference to the original (I think, again, use boost::ref to
> be sure)
> > Forgive me if this question seems stupid, but I am new to Lambda, fascinated
> > by its power, but convoluted by its mechanism yet.
> >
> > Thanks.
> >
> [snip]
>
> Don't worry about it, but don't forget to read the documentation!
> One more thing to keep in mind, the overload for '()', the call
> operator, for a lambda function object immeadiatly evaluates it's
> contained expression, ie:
> (_1 + 3)(4) == (4 + 3);
> to get around this if you want to delay a call to that object, use:
> boost::lambda::bind(_1 + 3, 4);
> which returns a lambda function object that when called, calls the first
> argument with the rest of bind's arguments as it's arguments, so:
> bind(_1 + 3, 4)() == (_1 + 3)(4) == (4 + 3)
> Which is VERY usefull if you want to, say call functions in a STL container:
>
> int i, j;
> std::vector<void(*)(int, int)> some_funcs;
> ...
> std::for_each(some_funcs.begin(), some_funcs.end(), bind(*_1, i, j));
>
> Although, Boost.Signals is probably a better bet if you do stuff like
> that a bit.
>
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net