# Proto :

Subject: Re: [proto] restructuring expression
From: Karsten Ahnert (karsten.ahnert_at_[hidden])
Date: 2012-05-30 19:22:10

On 05/30/2012 06:25 PM, Eric Niebler wrote:
> On 5/29/2012 3:29 PM, Karsten Ahnert wrote:
>> On 05/29/2012 08:21 PM, Eric Niebler wrote:
>>> On 5/29/2012 1:44 AM, Karsten Ahnert wrote:
>>>> I have an arithmetic expression template where multiplication is
>>>> commutative. Is there an easy way to order a chain of multiplications
>>>> such that terminals with values (like proto::terminal< double >) appear
>>>> at the beginning? For example that
>>>>
>>>> arg1 * arg1 * 1.5 * arg1
>>>>
>>>> will be transformed to
>>>>
>>>> 1.5 * arg1 * arg1 * arg1
>>>>
>>>> ?
>>>>
>>>> I can imagine some complicated algorithms swapping expressions and child
>>>> expressions but I wonder if there is a simpler way.
>>>
>>> There is no clever built-in Proto algorithm for commutative
>>> transformations like this, I'm afraid. I was going to suggest flattening
>>> to a fusion vector and using fusion sort, but I see there is no fusion
>>> sort! :-( Nevertheless, that seems like a promising direction to me.
>>> Once you have the sorted vector, you should(?) be able to use
>>> fusion::fold to build the correct proto tree from it.
>>
>> Ok, this looks promising. But I failed to get proto::fold to work. As a
>> first step I tried to flatten an expression and reconstruct it with
>> proto::fold:
>>
>> struct back_fold :
>> proto::fold<
>> proto::_ ,
>> proto::_state ,
>> proto::functional::make_multiplies( proto::_state , proto::_ )
>> > { };
>>
>> template< class Expr >
>> void eval( const Expr &e )
>> {
>> back_fold b;
>> proto::display_expr(
>> b( proto::flatten( e ) , proto::_make_terminal()( 1.0 ) )
>> );
>> }
>>
>> eval( 2.0 * arg1 * arg1 * arg1 * 1.0 );
>>
>> Unfortunately this does not compile. Any ideas what is wrong here?
>
> Yes, I know. I said you should use fusion::fold, not proto::fold. Once
> you flatten a proto expression, you get a fusion sequence. That means
> you have to use a fusion algorithm on it. Proto's transforms expect
> their first parameter to be proto expression trees. The result of
> proto::flatten is emphatically not.
>

ok, this makes sense. Next trial:

template< typename I > struct placeholder : I {};

proto::terminal< placeholder< mpl::size_t< 0 > > >::type const arg1 = {};

proto::display_expr(
fusion::fold(
proto::flatten( arg1 ) ,
proto::functional::make_terminal()( 1.0 ) ,
proto::functional::make_multiplies()
)
);

gives a compilation error:

/boost/proto/fusion.hpp:86:20: error: no type named ‘proto_tag’ in
‘const struct placeholder<mpl_::size_t<0ul> >

It is difficult for me to figure out what happens here. Any ideas?

Proto list run by eric at boostpro.com