On 10/4/2010 10:57 PM, Thomas Heller wrote: > Eric Niebler wrote: >> On 10/4/2010 12:20 PM, Thomas Heller wrote: >>> the new thing i added is transform_expr, which works like >>> fusion::transform: It creates the expression again, with transformed >>> child nodes (the child nodes get transformed according to the transform >>> you specify as template parameter >> >> How is that different than what the pass_through transform does? > > It works slightly different than pass_through: > > transform_expr calls > when<_, Fun>::template impl<typename result_of::child_c<Expr, N>::type, > State, Data> > while pass_through calls > Grammar::proto_childN::template impl<typename result_of::child_c<Expr, > N>::type, State, Data> > > Truth is, I could not see how I could use pass_through to do what I wanted, > and still fail to see what pass_through really does. Another truth is, that > i initially wanted to call transform_expr pass_through until I realized that > it is already there. > Perhaps you can sched some light on why pass_through is implemented that > way.
Getting caught up on this discussion and realized I never responded to this. It seems to me that: transform_expr< Fun > is equivalent to: nary_expr< _, vararg< when<_,Fun> > > with some extra handling for terminals. (The default transform of the nary_expr grammar is implemented in terms of pass_through.) Transform_expr applies the Fun transform to terminals also, but pass_through doesn't do anything to terminals. That's because, in my experience, transforms that work for non-terminals rarely work as-is for terminals. Is your experience different? So it really seems to me that transform_expr is not necessary, but I may be wrong. As to why pass_through is implemented as it is, the idea is to make it as easy as possible to apply global transformations to specific sub-expressions while leaving the rest of the tree structure unmodified. For instance, if you want to change all ints to floats in an expression tree, you would do (untested): struct Int2Float : or_< when< terminal<int>, terminal<float>::type(_value) > , nary_expr< _, vararg< Int2Float > > > {}; This takes an expression tree and produces a new one where all int terminals have been converted to float terminals. IIUC, using transform_expr, it would look like this: struct Int2Float : or_< when< terminal<int>, terminal<float>::type(_value) > , otherwise< transform_expr< Int2Float > > > {}; Is that right? If so, Proto's pass_through transform is more flexible, because it allows different transforms to be applied to different children. For instance: plus< Alg0, Alg1 > is a grammar that matches plus nodes in the expected way, and an algorithm that builds a new plus node where the 0th child is the result of applying Alg0 to the left child and Alg1 to the right. IIUC, transform_expr doesn't allow this flexibility. -- Eric Niebler BoostPro Computing http://www.boostpro.com _______________________________________________ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto