Quick start |
To get a first glimpse on what the Phoenix framework offers, let us start with an example. We want to find the first odd number in an STL container.
1) Normally we use a functor or a function pointer and pass that in to STL's find_if generic function (sample1.cpp):
Write a function:
bool
is_odd(int arg1)
{
return arg1 % 2 == 1;
}
Pass a pointer to the function to STL's find_if generic function:
find_if(c.begin(), c.end(), &is_odd)
2) Using Phoenix, the same can be achieved directly with a one- liner (sample2.cpp):
find_if(c.begin(), c.end(), arg1 % 2 == 1)
The expression "arg1 % 2 == 1" automagically creates a functor with the expected behavior. In FP, this unnamed function is called a lambda function. Unlike 1, the function pointer version, which is monomorphic (expects and works only with a fixed type int argument), the Phoenix version is completely polymorphic and works with any container (of ints, of doubles, of complex, etc.) as long as its elements can handle the "arg1 % 2 == 1" expression.
3) Write a polymorphic functor using Phoenix (sample3.cpp)
struct is_odd_ {
template <typename ArgT>
struct result { typedef bool type; };
template <typename ArgT>
bool operator()(ArgT arg1) const
{ return arg1 % 2 == 1; }
};
function<is_odd_> is_odd;
Call the lazy is_odd function:
find_if(c.begin(), c.end(), is_odd(arg1))
is_odd_ is the actual functor. It has been proxied in function<is_odd_> by is_odd (note no trailing underscore) which makes it a lazy function. is_odd_::operator() is the main function body. is_odd_::result is a type computer that answers the question "What should be our return type given an argument of type ArgT?".
Like 2, and unlike 1, function pointers or plain C++ functors, is_odd is a true lazy, polymorphic functor (rank-2 polymorphic functoid, in FC++ jargon). The Phoenix functor version is fully polymorphic and works with any container (of ints, of doubles, of complex, etc.) as long as its elements can handle the "arg1 % 2 == 1" expression. However, unlike 2, this is more efficient and has less overhead especially when dealing with much more complex functions.
This is just the tip of the iceberg. There are more nifty things you can do with the framework. There are quite interesting concepts such as rank-2 polymorphic lazy functions, lazy statements, binders etc; enough to whet the appetite of anyone wishing to squeeze more power from C++.
Copyright © 2001-2002 Joel de Guzman
Permission to copy, use, modify, sell and distribute this document
is granted provided this copyright notice appears in all copies. This document
is provided "as is" without express or implied warranty, and with
no claim as to its suitability for any purpose.