Boost logo

Boost :

Subject: Re: [boost] Rave for proposed Boost.Local (functions)
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-02-05 12:03:40


On Wed, Feb 2, 2011 at 2:00 AM, Thomas Heller
<thom.heller_at_[hidden]> wrote:
> Gregory Crosswhite wrote:
>
>> Hey everyone,
>>
>> The purpose of this e-mail is to rave about Lorenzo's proposed
>> Boost.Local library in the hopes of inspiring people to start the review
>> process for it.  :-)
>>
>> I have been experimenting with using this library in my own code, and it
>> has been a godsend for me.  In one of the projects I have been working
>> on I ran into many situations where I needed to call a higher-order
>> function with a closure, and the closure was just complicated enough
>> that I couldn't use Boost.Lambda.  Before using this library I
>> frequently found myself either writing a lot of extra code to
>> work-around the need for a higher-order function, or writing a lot of
>> boilerplate to create classes that would only be used by a single
>> function in order to create a function object.  This library has let me
>> write the closures that I need in a fairly painless fashion and so has
>> made my life a lot easier!
>
> I would be interested in what limitations you ran into using Boost.Lambda
> and if you are aware of the recent efforts that were put into Boost.Phoenix?
>
>> To my mind this example looks a lot clearer if you reformat it as follows:
>>
>>          BOOST_LOCAL_FUNCTION(
>>              (void) (add)(
>>                  (double)(num)
>>                  (const bind)((factor))
>>                  (bind)((&sum))
>>              )
>>          ) {
>>              sum += factor * num;
>>              std::clog<<  "Summed: "<<  sum<<  std::endl;
>>          } BOOST_LOCAL_FUNCTION_END(add)
>>          add(100.0);
>
> As far is a am concerned, I still find this syntax overly verbose.
> I do realize though that this is just a toy example. For better comparison,
> Here is how the same thing would like in Boost.Phoenix:
>
> boost::function<void(double)> add
>    =(
>        ref(sum) += factor * _1,
>        std::clog << var("Summed: ") << sum << std::endl
>     )
>    ;
> add(100.0);

Can you make factor constant within add() body using Boost.Phoenix? If
not, then I could not use Boost.Phoenix for my original use case* that
motived Boost.Local (local constant blocks). And that's why C++0x
lambdas are also not useful for me because they do not support
constant binding -- why don't they?? :(( -- plus I use an oldish
gcc-based tool chain for an embedded system and there is no plan to
get a C++0x release for it at the moment...

(*) My original use case required (1) to write the body is normal C++
syntax (so I could not use Boost.Phoenix) and (2) to use constant
binding (I am not sure but I don't think Boost.Phoenix can do constant
binding, I know C++0x lambdas cannot) to check assertions in a
constant correct context:

    void f(int& zero) {
        BLOCK_INVARIANT( (const (zero) (zero == 0)) ) // Compiler
error if programmers mistake `==` with `=`.
        ...
    }

I can do this with Boost.Local:

    void f(int& zero) {
        BOOST_LOCAL_BLOCK( (const bind)(&zero) ) {
            assert(zero == 0);
        } BOOST_LOCAL_BLOCK_END
    }

How can I do this in Boost.Phoenix? How can I do this in C++0x
lambdas? (Note requirements (1) and (2).)

Maybe this use case is not very interesting to other people but it was
important for me.

> Despite the Local Blocks and Local Exits feature, I can't see much
> difference to the already existing lambda libraries.
> I just looked through the Boost.Local documentation and immediately
> navigated to the "Alternatives" section and its not really correct regarding
> the features of Boost.Lambda and Boost.Phoenix. I am specifically talking
> about the "Bind variables in scope" and "Program body using usual C++

The Alternatives section is based on this previous Boost discussion
http://permalink.gmane.org/gmane.comp.lib.boost.devel/212255 .
I also think it is not a complete comparison. For example, I wanted to
add the add() example -- add add() ;) -- reworked in Boost.Phoenix,
Boost.Lambda, C++0x lambdas, and C++ local classes but I didn't have
time yet... Thanks a lot of the above code in Boost.Phoenix, I'll add
it to Boost.Local doc :)

> syntax" part. The last is debatable, but how are the above examples (both of
> Boost.Local and Boost.Phoenix) not C++ syntax?
> Can you highlight the advantages/disadvantages again?

Yes, this is debatable and at the end it's of course all C++. But the
Boost.Local function body defined within `{ ... }` it's the normal C++
syntax for function definitions. For example, Boost.Phoenix uses `,`
where C++ and Boost.Local use `;` to terminate and instruction,
Boost.Phoenix uses `var("Summed:")` where C++ and Boost.Local use
`"Summed:"`, etc.

Plus, how would local variables and local classes look in
Boost.Pheenix? In Boost.Local it's like in normal C++:

          BOOST_LOCAL_FUNCTION(
              (void) (add)(
                  (double)(num)
                  (const bind)((factor))
                  (bind)((&sum))
              )
          ) {
              const std::string msg = "Summed: "; // A const local var.
              struct text { std::string say; } // A local struct.
              test t; // A local var.
              t.say = msg;

              sum += factor * num;
              std::clog<< t.say <<  sum<<  std::endl;
          } BOOST_LOCAL_FUNCTION_END(add)
          add(100.0);

How would this look in Boost.Phoenix? I wish I knew Phoenix better :)
so I could provide the answers myself...

-- 
Lorenzo

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