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