From: Jaakko Jarvi (jajarvi_at_[hidden])
Date: 2002-03-26 14:27:49
This has been an interesting review (it is still ongoing, so who knows
what will come up), to say the least!
I've taken a close look at Phoenix and believe to have an understanding
of both libraries. The three main things that make them different are
1) In Phoenix actor (lambda_functor) template inherits from it's
single template parameter, rather than a template with a fixed name
With this arrangement, as Joel has pointed out, there is more freedom in
defining extensions (statemetns, closures, local variables ...)
2) The outermost return type deduction layer in LL works as
whereas in Phoenix the scheme introduced in FC++ is used:
Both are equally powerful, the latter lets one have the evaluation
function and the return type metafunction within the same class,
wheras in the former, the metafunction is in a specialization of
some other template class.
3) LL passes the actual arguments to the lambda functors as such all the
way to the underlying operators, whereas Phoenix bundles them into a tuple
object. Using tuples, makes it more convenient to define the eval
functions (only one argument instead of N, where N is the max number of
placeholders), but comes with a performance hit. KCC optimizes the tuple
away, but e.g. gcc3 cannot, making particularly the simplest lambda
expressions significantly slower.
Strict/weak arity, etc. are interface issues and can go either way in
either library, it's a matter of agreeing (and people seem to strongly
believe in weakness).
I also took a close look at LL, and experimented a bit:
I changed to scheme 1) above, which was straightforward. Lambda
functors still inherit from the same base class, the expression that
names that base class within the lambda functor class is just different.
The interface functions didn't have to change either.
I dropped the strict arity (it can still be added back :):) ), which
let one go from several lambda_functor instantiations to just one.
I replaced the outermost return_type deduction layer with scheme 2)
above. The hard work of return type deduction is still done with the
same templates as before (the templates that decide what is the result
of operatorX given types A and B etc).
As a result, Phoenix if_().else_ construct, and the closure
implementation and the closure test, compile and
run after trivial naming changes.
And the test cases in the libs/lambda/test still compile and run.
(Except for currying, which I did not add yet to the changed return
type deduction framework.)
So incorporating the first two Joel's ideas above make the libraries
really similar and it really makes no sense to have two
such libraries in Boost.
We have discussed with Joel, and have agreed on to
strive for a merged library (be it LL revision 2), which will
hopefully have the best of both libraries.
In the meanwhile, including the LL under review gives the
convenient functors for the end users right now,
the next LL/Phoenix merged revision
will provide the extendability that brings local variables, closures ...
with it, still having the end user functors.
Compared to the LL now under review, the interface
should remain the same. (Apart form the issues with the control
statement syntaces). As someone pointed out, going from strict arity
to weak arity does not break existing code.
In an earlier posting, Dave A. questioned whether a formal review is the
means to get to the best solutions. I believe it has worked with this
review, incorporating Joel's ideas really do give advantages.
I hope this solution satisifies all parties (even Asger),
-- -- -- Jaakko Järvi email: jajarvi_at_[hidden] -- Post Doc Fellow phone: +1 (812) 855-3608 -- Pervasive Technology Labs fax: +1 (812) 855-4829 -- Indiana University, Bloomington
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk