Boost logo

Boost :

Subject: Re: [boost] New libraries implementing C++11 features in C++03
From: Lorenzo Caminiti (lorcaminiti_at_[hidden])
Date: 2011-11-24 04:16:31


On Wed, Nov 23, 2011 at 8:11 PM, Joel de Guzman
<joel_at_[hidden]> wrote:
> On 11/24/2011 8:06 AM, Brent Spillner wrote:
>> On 23 Nov 2011 10:21:50 Joel de Guzman wrote:
>>> a good approximation of lambda is already existing in Boost. Namely: bind,
>>> lambda and phoenix. I posted a Spirit example of lambda in action using
>>> Phoenix:
>>>
>>> http://tinyurl.com/7w2h2r9
>>>
>>> Try as hard as you can, but you cannot ever come close to the clarity of
>>> he syntax presented there. Proponents of locals have cited error-messages
>>> generated by the compiler as a justification for Locals. Locals is probably
>>> a good workaround. But hear me out...
>>
>> First of all, this "trivial" example didn't even compile on the first
>> machine I tried it on, which had Boost 1.45 (which doesn't expose
>> qi:_val_type or qi:_1_type).  This is a pretty good reminder of the
>
> Man! Of course you should use the examples in 1.45. Those examples
> are for 1.48 and uses new features implemented in 1.48! Sheesh!
>
>> On a machine with 1.48, the example compiles just fine.  If you were
>> to pass std::string::iterators instead of const_iterators to
>> phrase_parse(), though ( a pretty common class of mistake in the real
>> world), you get this error message (GCC 4.4.4):
>>
>
> Double Sheesh! If you've spent even a few seconds looking into the
> error (beyond fault-finding), you will see that a simple textual
> search of "error" will reveal this:
>
>> ------------------- Horrific error messages follow ---------------------
>
> calc3.cpp:90:   instantiated from here
> /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:176: error: no
> matching function for call to
> 'assertion_failed(mpl_::failed************
> (boost::spirit::qi::rule<Iterator, T1, T2, T3,
> T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const
> Expr&, mpl_::false_)
>
> [snip ... some complex types]
>
> ::error_invalid_expression::************)
>
> And double clicking on it using your editor will lead you here:
>
>        static void define(rule& lhs, Expr const& expr, mpl::false_)
>        {
>            // Report invalid expression error as early as possible.
>            // If you got an error_invalid_expression error message here,
>            // then the expression (expr) is not a valid spirit qi expression.
>            BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
>        }
>
> If you've read the Spirit docs, you will know what that means.
>
> Now having said that, and before I leave this thread, let me remind
> everyone that **you can also have statement syntax in Phoenix** if you
> have a complex statement and you fear writing complex phoenix lambda
> expressions. It's called phoenix::functions.
>
> In fact here's what I advocate:
>
> 1) For simple 1-2-3 liners, use a phoenix lambda expression. It's hard
>   to get them wrong. For example, you'll have to be absurdly dumb to
>   get this wrong:
>
>     auto plus = _1 + _2;
>
> 2) For more complex expressions, especially those involving statements,
>   use a phoenix function plus a simple lambda expression that forwards
>   to the phoenix function. Example:
>
>     for_each(f, l, call_complex_function(_1));

IF (this is a big IF) I understand it correctly, Phoenix functions are
non-local functors:
http://www.boost.org/doc/libs/1_48_0/libs/phoenix/doc/html/phoenix/starter_kit/lazy_functions.html

// non-local scope
struct is_odd_impl
{
    typedef bool result_type;

    template <typename Arg>
    bool operator()(Arg arg1) const
    {
        return arg1 % 2 == 1;
    }
};

// local scope
function<is_odd_impl> is_odd;

A couple of people have argued that for complex task it is OK to push
the code to non-local scope. That is their point of view but of course
it goes fundamentally against local functions principles (e.g., N2511)
and the fact that even local functions can be long in some programming
style (as expressed by others commenting before).

IMO, our library users should be felt the opportunity to program as
they see more fit to themselves and their problem domain (long/short
local functions, long/short global Phoenix functions, long/short
Phoenix lambdas ( yes, even long Phoenix lambdas if the users want to)
).

HTH,
--Lorenzo


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