Boost logo

Boost :

Subject: Re: [boost] phoenix::bind
From: Joel de Guzman (joel_at_[hidden])
Date: 2008-10-02 08:04:36


Joel de Guzman wrote:
> Giovanni Piero Deretta wrote:
>
>>> 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);
>
> No. Not unless you bind f.

Ok, I think this is it! This is the main misunderstanding about
phx::for_each and all phoenix functions that take in other
functions.

All phoenix expressions must be a legitimate phoenix actor
(following the actor concept). That is obvious in other contexts.
For example, given a plain function object f:

     struct f { int operator()(int i); };

you can't just write:

     f(_1) + val(123) // error f can't take a _1 argument

you need to either:

1) bind it
2) make a phoenix function out of it

So:

     phx::for_each(_1, f)(some_range);

is an error. f is not an actor. Hence, make it one. Let's use bind:

     phx::for_each(_1, bind(f, _1))(some_range);

now, that is still in error:

1) The placeholders are eagerly substituted.
2) After substituting _1 the result of the bind:

     f(some_range)

has the wrong call.

So, you'll want to protect it. In phoenix, we use "lambda":

     phx::for_each(_1, lambda[bind(f, _1)])(some_range);

Assuming phoenix had "unlambda" (which BTW is very easy to do),
We're back to square one. Phoenix does not allow arbitrary
functions/function objects as the function argument to
for_each (or any phoenix function that takes in a higher-order
function. It must be a phoenix actor.

Regards,

-- 
Joel de Guzman
http://www.boostpro.com
http://spirit.sf.net

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk