Boost logo

Boost Users :

Subject: Re: [Boost-users] [phoenix][lambda] lambda to phoenix translation: get sig (signature) from actor
From: Joel de Guzman (joel_at_[hidden])
Date: 2010-06-02 20:00:37


On 6/2/10 5:03 PM, alfC wrote:
> On May 31, 3:07 am, Joel de Guzman<j..._at_[hidden]> wrote:
>> What are the args to LambdaExp?
>
> ok, I think I simplified the code as much as possible to its bare
> bones, here it is a compilable example of what I need.
> as you see first there is a lambda version which is concise and works,
> then follows the phoenix attempt.
> I have and expression template _1 + 1. or arg1 + 1. and I am trying to
> compose it with two free functions (sq and div2).
> Take _1 + 1. or arg1 + 1. as black box (this is an example of what the
> subexpression that the pattern matching recognizes in the full
> example).
>
> The precise question is what is the phoenix translation of the lambda
> "bind(&div2, (_1+1.)(bind(&sq, _1) ) )" ?
> [ _1+1. is just an example, in the real code is some argument passed
> and can be any expression, in other words "(_1+1.)" must remain there,
> so (bind(&div2, (bind(&sq,arg1) ) + 1. ) is not the answer I am
> looking for].
>
> the full minimal example is below:
>
> #include<boost/function.hpp>
> #include<boost/spirit/home/phoenix.hpp>
> #include<boost/lambda/lambda.hpp>
> #include<boost/lambda/bind.hpp>
>
> double sq(double x){return x*x;}
> double div2(double x){return x/2.;}
> using namespace std;
> int main(){
> {// first with lambda
> using namespace boost::lambda;
> double const dos = 2.;
> boost::function<double(double)> f( bind(&div2, (_1+1.)(bind(&sq,
> _1) ) ) );
> cout<< f(dos)<< endl; // returns 2.5
> }
> {// second with phoenix
> using namespace boost::phoenix;
> using namespace boost::phoenix::arg_names;
> double const dos = 2.;
> // boost::function<double(double)> f( (bind(&div2, (arg1+1.)
> (bind(&sq,arg1) ) ) )); //doesn't work, what goes here??
> // cout<< f(dos)<< endl; // should return 2.5
> }
> return 0;
> };
>
>
> I tried all sorts of things, I am starting to think that Phoenix is
> not designed for this (although it is supposed to be a generalization
> of BLL.)

You are right. Phoenix is not designed to compose that way.
I've taken note of this use case and it probably be incorporated
into 3.0.

However, take note that we do things differently in Phoenix.
This use case is typically done using phoenix::functions and
phoenix higher order functions called phoenix::lambda. Here's
how I would write your code in Phoenix:

First, I'll start with a phoenix function taking in a higher order
phoenix function: _1+1.

     boost::function<double(double)> f
         = divdoub(_1, lambda[_1+1.0]);

divdoub is trivial to write. See attached for complete code.
Things to note:

* This is much more efficient than nested binds
* It is polymorphic, bind is monomorphic
* Client code is easier to read (I never really liked nested
   binds).
* It is easier to compose: composition is just a function object
   like any other, wrapped in a phoenix::function. No messy
   introspection.
* While there's more code to write, the extra code is typically
   part of a library. See phoenix algorithms and containers, for
   example, which wraps STL containers and algorithms as lazy
   functions.

Hope that helps.

Regards,

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



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