Boost logo

Boost :

Subject: Re: [boost] Case study: Boost.Local versus Boost.Phoenix
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-02-06 10:29:42


On Sun, Feb 6, 2011 at 8:24 AM, Edward Diener <eldiener_at_[hidden]> wrote:
> On 2/5/2011 4:04 PM, Lorenzo Caminiti wrote:
>>
>> On Fri, Feb 4, 2011 at 10:55 AM, Mathias Gaunard
>> <mathias.gaunard_at_[hidden]>  wrote:
>>>
>>> On 04/02/2011 13:35, Artyom wrote:
>>>
>>>> I'm sorry is it only me or it would be much more readable
>>>> and maintainable to write:
>>>>
>>>> namespace {
>>>>    struct my_lambda  {
>>>>        foo_type&foo;
>>>>        bar_type&bar
>>>>        my_lambda(foo_type&local_foo,bar_type&local_bar) :
>>>>            foo(local_foo),
>>>>            bar(local_bar)
>>>>        {
>>>>        }
>>>>
>>>>        void operator()(a_type a) const
>>>>        {
>>>>              /// Your body goes there
>>>>        }
>>>>
>>>>    };
>>>> }
>>>>
>>>> void my_function()
>>>> {
>>>>     foo_type foo;
>>>>     bar_type bar;
>>>>
>>>>     my_lambda lambda(foo,bar);
>>>>     for_each(as.begin(),as.end(),lambda);
>>>>     // or something else
>>>> }
>>>
>>> That's exactly the kind of thing Boost.Local does, it generates that
>>> structure but avoids you the boilerplate of declaring foo and bar members
>>> and forwarding them in the constructor. Also, it uses Boost.Typeof, so
>>> you
>>> don't have to write their type.
>>>
>>> Also, it is much more valuable to declare this as
>>>
>>> void my_function()
>>> {
>>>    foo_type foo;
>>>    bar_type bar;
>>>
>>>    struct
>>>    {
>>>       foo_type&foo;
>>>       bar_type&bar
>>>       my_lambda(foo_type&local_foo,bar_type&local_bar) :
>>>           foo(local_foo),
>>>           bar(local_bar)
>>>       {
>>>       }
>>>
>>>       void operator()(a_type a) const
>>>       {
>>>             /// Your body goes there
>>>       }
>>>
>>>    } lambda(foo, bar);
>>>    for_each(as.begin(),as.end(),lambda);
>>>    // or something else
>>> }
>>>
>>> since the lambda is right next to where it is used (which is the whole
>>> point
>>> of the exercise).
>>>
>>> It is true however that the syntax of the Boost.Local macro could greatly
>>> be
>>> simplified.
>>>
>>> I think
>>>
>>> LOCAL_FUNCTION(R, f, (a, b, c)(T0 a0, T1 a1), body)
>>>
>>> is a better syntax. (a, b, c) would catch a, b, and c in the scope and
>>> would
>>> be optional.
>>>
>>> (Of course, it requires the use of the C99 preprocessor)
>>
>> Sorry, C++ preprocessor only -- that was a requirement for me... (Can
>> you imagine how much the syntax can be simplified with varidiac
>> macros... I can!! Too bad I can't use them...).
>
> For the purposes of Boost compatibility you can use variadic macros as long
> as BOOST_NO_VARIADIC_MACROS is not defined.
>
> You can also use my variadic_macro_data library in the sandbox to
> interoperate variadic macros with Boost PP and to simplify some Boost PP
> regarding tuples when variadic macros is supported.
>
> So you might be able to offer a clearer syntax for your macros for those
> compilers which do support variadic macros ( there are quite a few of them )
> if you wanted to do so, even though it does not fit your own needs. But this
> is of course totally up to you.
>
> The downside to variadic macros, which Boost PP data types do not share, is
> that variadic macro notation can only be used as the last parameter of any
> given macro.

On Sat, Feb 5, 2011 at 12:42 PM, Steven Watanabe <watanabesj_at_[hidden]> wrote:
> AMDG
>
> On 2/5/2011 9:26 AM, Lorenzo Caminiti wrote:
>>
>> On Fri, Feb 4, 2011 at 5:03 PM, Alexander Nasonov<alnsn_at_[hidden]>  wrote:
>>>
>>> Steven and I were playing with different syntaxes few years ago
>>>
>>> We came up with something like this:
>>>
>>>    void BOOST_LOCAL_FUNCTION
>>>        ( BOOST_BIND((factor)(&sum)), double num )
>>>    {
>>>        sum += factor * num;
>>>        std::clog<<    "Summed: "<<    sum<<    std::endl;
>>>    }
>>>    BOOST_LOCAL_FUNCTION_DECL(add)
>>>
>>> http://thread.gmane.org/gmane.comp.lib.boost.devel/168612/focus=168694
>>
>> Yes, Alex that is exactly where I started and I cannot thank you
>> enough for your Boost.ScopeExit work which has served as a solid basis
>> for my Boost.Local development.
>>
>> However:
>> 1) How is this syntax is preferable to Boost.Local parenthesized
>> syntax? To me, there is not much difference.*
>
> The argument list is more readable, because it's
> closer to normal C++ syntax.
>
>> 2) How would you pass multiple local function parameters (not just the
>> one parameter `num`) using this syntax?
>
> Black magic.  I don't remember how, but
> I know we did figure this out.
>
>> 3) Can you generate local function that are passed as template
>> parameters using this syntax?
>>
>
> I think so.  It wouldn't be very useful otherwise
> would it?

OK, I can take as a homework to look into how variadic macros and the
Alex-Steven* macro syntax could be used to replace or improve the
parenthesized syntax to declare local functions.

However, I would be much more motivated to look into
improving/changing the parenthesized syntax if people that have
actually used the syntax report a bad experience with it -- instead
than just because the parenthesis don't generate love at first sight
:)

(*) A _possible_ issue with Alex-Steven syntax is that it does not
separate the parameter types from the parameter names. I cannot
program the preprocessor to retrieve type and name separately from
`double num` -- while I can from `(double)(num)` or `double, num` --
but I think I need the type to pass it as a template parameter to
create the functor type `function<int (double)>`... the same issue
_could_ be present for the eventual macros to wrap Phoenix's function.
Maybe there are ways to do this at compile-time instead that a
preprocessing-time using template metaprogramming...

-- 
Lorenzo

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