Eric Niebler <e...@...> 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 mailing list
proto@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/proto

Reply via email to