
On Thu, Oct 2, 2008 at 4:46 AM, Joel de Guzman <joel@boost-consulting.com> wrote:
Peter Dimov wrote:
Joel de Guzman:
Maybe you want:
let(_a = 0)[ ++_a ]
Maybe I do. :-)
phx::for_each(_1, lambda[std::cout << _1 << std::endl])
Notice that like protect, there are two function invocations happening here.
The confusion here comes from the fact that the above would work if lambda[] had "unlambda" semantics, that is, if it returned a function object that was not a phoenix expression.
No, that is not the "unlambda" semantics. There needs to be 2 function application there: 1) the one that substitutes the stl container for _1 (the leftmost _1) and 2) the one that substitutes the container's element for _1 (the rightmost _1). The key point here is that phx.lambda (and BLL protect), *returns a lambda-functor that returns a lambda-functor*. unlambda OTOH simply returns a plain functor (non-actor). A plain functor can only do one function application (bear in mind that this is phoenix for_each (lazy), not std::for_each (eager)).
Ok, follow me: let 'f' me an unary function object, one suitable as a parameter to for_each: Am I right that the following calls should work and apply every element of some range to 'f'? phx::for_each(_1, f)(some_range); Ok, now 'f' is unlambda(std::cout << _1 << std::endl) (assuming phoenix had unlambda with the same semantics of boost::lambda::unlambda. Isn't the previous example still supposed to work? From phoenix point of view, the internal lambda expression is masked so it is treated as any other function object. The problem is of course that this prevent binding local lambda variables to placeholders of the outer lambda expression: phoenix will not recongnize the result of lambda[] as part of the lambda expression but will treat it as an opaque function object, so it there is no extra evaluation round for binding the actual arguments of the outer lambda expression to the local variables. Still I'm sure you can come out with a protocol to do that without requiring the extra round to be shown to the user.
Here's the crucial difference (using BLL) highlighting the difference:
{ int x = 5; int r = bind(_1, _2)(unlambda(_1), x); BOOST_TEST(x == 5); }
{ int x = 5; int r = bind(_1, _2)(protect(_1)(), x); BOOST_TEST(x == 5); }
Notice that protect *requires* the additional function application:
protect(_1)()
I understand the difference, but what buys us? What is the advantage? It feels a bit like an internal detail leaking... -- gpd