On 11/18/2010 1:45 PM, Thomas Heller wrote: > Eric Niebler <e...@...> writes: >> On 11/18/2010 6:09 AM, Thomas Heller wrote: >>> Here goes the renumbering example: >>> http://codepad.org/K0TZamPb > <snip> >> Unfortunately, this doesn't actually solve the reevaluation problem ... >> it just hides it. > > Yes, exactly. > >> If "_a" gets replaced eagerly everywhere with >> "Renumber(_, second(proto::_state))", then that transform will actually >> get run every time. What I want is a way to evaluate the transform, >> store the result in a temporary, and have "_a" refer to that temporary. > > Yes, I thought of doing this ... but could not find a solution. The question > is, > do we really need this behaviour? Is replacement not enough? > Could you make up a usecase? I can not think of one ... Regarding that > counting > example ... it can be solved by this pair hack.
The Renumber example is itself a use-case. I had to hack around the lack
of this feature with the silly type_of transform:
struct RenumberFun
: proto::fold<
_
, make_pair(fusion::vector0<>(), proto::_state)
, make_pair(
push_back(
first(proto::_state)
, first(Renumber(_, second(proto::_state)))
)
, type_of<second(Renumber(_, second(proto::_state))) >
)
>
{};
That should simply be:
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))
, second(_a)
)
>
>
{};
See? If Renumber gets invoked once and the result "stored" in _a, then
we can just do first(_a) and then second(_a) and not incur any runtime
overhead. type_of was a hack that took advantage of the fact that the
result of second(_a) contains no interesting runtime state (it's just a
MPL int_). There will be times when that's not the case.
>> It's REALLY hard. The let context needs to be bundled with the Expr,
>> State, or Data parameters somehow, but in a way that's transparent. I
>> don't actually know if it's possible.
>
> Very hard ... yeah. I am thinking that we can maybe save these variables in
> the
> transform?
I'm thinking we just stuff it into the Data parameter. We have a
let_scope template that is effectively a pair containing:
1. The user's original Data, and
2. A Fusion map from local variables (_a) to values.
The let transform evaluates the bindings and stores the result in the
let_scope's Fusion map alongside the user's Data. We pass the let_scope
as the new Data parameter. _a is itself a transform that looks up the
value in Data's Fusion map. The proto::_data transform is changed to be
aware of let_scope and return only the original user's Data. This can
work. We also need to be sure not to break the new
proto::external_transform.
The problems with this approach as I see it:
1. It's not completely transparent. Custom primitive transforms will see
that the Data parameter has been monkeyed with.
2. Local variables like _a are not lexically scoped. They are, in fact,
dynamically scoped. That is, you can access _a outside of a let<>
clause, as long as you've been called from within a let clause.
Might be worth it. But as there's no pressing need, I'm content to let
this simmer. Maybe we can think of something better.
--
Eric Niebler
BoostPro Computing
http://www.boostpro.com
signature.asc
Description: OpenPGP digital signature
_______________________________________________ proto mailing list [email protected] http://lists.boost.org/mailman/listinfo.cgi/proto
