Hello Y'all, Yesterday, I sent in phoenix code that implements true local variables. With a slight twist, the code can be made to return values as was suggested in the list. Like before, no changes to the original framework is needed. This is yet another example demonstratintg phoenix's extensibility. First, sample code. Find the first element > 5, print each element as we traverse the container c. Print the result if one is found (sample8.cpp): iterator it = find_if(c.begin(), c.end(), context<bool>() [ cout << arg1, result = arg1 > 5, if_(!result) [ cout << val(", ") ] .else_ [ cout << val(" found result == ") << arg1 ] ] ); Changes to yesterday's code: 1) locals is renamed as context 2) The first type in the context-type list is the return type. Examples: bool return type, no locals: context<bool>() bool return type, int local: context<bool, int>() std::string return type, char const* local initialized to "hello", int local: context<std::string, char const*, int>("hello") void return type, int local initialized to 3 context<void>(3) int return type, int local initialized to 3, std::string local initialized to "hello": context<int>(3, std::string("hello")) The return value "result" is actually just like another local variable, reminiscent of pascal. It would have looked more C++ like, syntax wise, to use return_(some_expression) but the semantics would have been more complex because a return(x) should exit the pseudo- function which is non-trivial to implement and to the best of my knowledge requires a throw of an exception that will be caught by the context object. This will have unwanted overhead and use of an exception as program flow-control is a no-no. *** contexts can be nested (of course). Especially useful in conjunction with statements which return void by default, as someone in the list (Stoll?) suggested. *** So here are the changes to yesterday's code: I ------------------------------ namespace locals { actor<local_var<0> > const result = local_var<0>(); actor<local_var<1> > const loc1 = local_var<1>(); actor<local_var<2> > const loc2 = local_var<2>(); actor<local_var<3> > const loc3 = local_var<3>(); actor<local_var<4> > const loc4 = local_var<4>(); } Yesterday's loc1..locN place-holders were in namespace phoenix. Now I put them in namespace phoenix::locals to avoid polluting the namespaces (short common names such as these are likely to clash). One can write: phoenix::locals::loc1 or: using namespace phoenix; locals::loc1 or: using namespace phoenix; using namespace phoenix::locals; loc1 Take note that actor<local_var<0> > is now named result. II ------------------------------ locals_composite is now remaned context_composite locals_gen is now remaned context_gen locals(...) gen functions is now context(...) gen functions III ------------------------------ context_composite::result is now written as: template <typename TupleT> struct result { typedef typename tuple_element<0, LocsT>::type type; }; Yesterday, it was: template <typename TupleT> struct result { typedef typename actor_result<ActorT, TupleT>::type type; }; The result of the context_composite is now the element zero (0) of the locals (LocsT) tuple. IV ------------------------------ context_composite::eval is now written as: template <typename TupleT> typename tuple_element<0, LocsT>::type eval(TupleT const& args) const { local_tuple<TupleT, LocsT> local_context(args, locals); actor.eval(local_context); return local_context.locs[tuple_index<0>()]; } Yesterday, it was: template <typename TupleT> typename actor_result<ActorT, TupleT>::type eval(TupleT const& args) const { return actor.eval(local_tuple<TupleT, LocsT>(args, locals)); } It's almost the same. The only difference is that the zeroth (0th) local variable is returned back to the caller of eval. V ------------------------------ context(...) gen functions (was locals(...)) accept one less initializer argument. The zeroth local (the return val) is always default constructed. ------------------------------ That's it. Have fun... Told 'ya phoenix is way cool! I wrote these changes in less than 20 mins. Tell me if this is useful and I will incorporate this in the framework. Suggestions welcome (as always). Cheers, --Joel