Boost logo

Proto :

Subject: Re: [proto] : Proto transform with state
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2010-11-18 06:09:17


Eric Niebler <eric_at_...> writes:
>
> On 11/17/2010 2:18 PM, joel falcou wrote:
> > On 17/11/10 19:46, Eric Niebler wrote:
> >> See the attached code. I wish I had a better answer. It sure would be
> >> nice to generalize this for other times when new state needs to bubble
> >> up and back down.
> >
> > Just chiming in. We had the exact same problem in quaff where needed to
> > carry on a process ID over the trasnform of parallel statement. If it can
> > make you worry less Eric, we ended with the exact same workaround.
>
> There's another issue. Look here:
>
> // don't evaluate T at runtime, but default-construct
> // an object of T's result type.
> template<typename T>
> struct type_of
> : proto::make<proto::call<T> >
> {};
>
> struct RenumberFun
> : proto::fold<
> _
> , make_pair(fusion::vector0<>(), proto::_state)
> , make_pair(
> push_back(
> first(proto::_state)
> //----------------------1
> , first(Renumber(_, second(proto::_state)))
> )
> //---------------------------2
> , type_of<second(Renumber(_, second(proto::_state))) >
> )
> >
> {};
>
> Notice that the Renumber algorithm needs to be invoked twice with the
> same arguments. In this case, we can avoid the runtime overhead of the
> second invocation by just using the type information, but that's not
> always going to be the case. There doesn't seem to be a way around it,
> either.
>
> I think Proto transforms need a "let" statement for storing intermediate
> results. Maybe something like this:
>
> struct RenumberFun
> : proto::fold<
> _
> , make_pair(fusion::vector0<>(), proto::_state)
> , let<
> _a( Renumber(_, second(proto::_state))> )
> , make_pair(
> push_back(
> first(proto::_state)
> , first(_a)
> )
> , type_of<second(_a) >
> )
> >
> >
> {};
>
> I haven't a clue how this would be implemented.
>
> It's fun to think about this stuff, but I wish it actually payed the bills.

Ok ... I implemented let!

Here goes the renumbering example:
http://codepad.org/K0TZamPb

The change is in line 296 rendering RenumberFun to:
struct RenumberFun
  : proto::fold<
        _
      , make_pair(fusion::vector<>(), proto::_state)
      , let<
            _a(Renumber(_, second(proto::_state)))
          , make_pair(
                push_back(
                    first(proto::_state)
                  , first(_a)
                )
              , type_of<second(_a) >
            )
>
>
{};

The implementation of let actually was quite easy ... here is how it works:

let<Locals, Transform> is a transform taking definitions of local variables and
the transform these locals will get applied to.
A local definition is in the form of: LocalName(LocalTransform)
If the specified transform has LocalName embedded, it will get replaced by
LocalTransform.
I also implemented the definition of more than one local ... this is done by
reusing proto::and_:

let<proto::and_<LocalName0(LocalTransform0), ... LocalNameN(LocalTransformN)>,
Transform>
The replacement is done from the end to the beginning, making it possible to
refer in a LocalTransformN to a LocalNameN-1, this gets replaced automatically!

Hope that helps!

Thomas


Proto list run by eric at boostpro.com