[phoenix] Basic recursive function.
I'm a newbie to Phoenix, just exploring, but I guess my intent in this code is obvious. Can anyone tell me what I'm doing wrong? Thx - Rob. #include <iostream> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/statement.hpp> #include <boost/function.hpp> using namespace boost::phoenix; using namespace boost::phoenix::arg_names; using namespace std; int main() { boost::function<unsigned( unsigned )> factorial; factorial = if_else( _1 == 0, 1, _1 * factorial( _1 - 1 ) ); cout << factorial( 3 ) << endl; return 0; }
At Wed, 13 Apr 2011 16:10:12 +0100, Robert Jones wrote:
I'm a newbie to Phoenix, just exploring, but I guess my intent in this code is obvious. Can anyone tell me what I'm doing wrong?
Thx
- Rob.
#include <iostream> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/statement.hpp> #include <boost/function.hpp>
using namespace boost::phoenix; using namespace boost::phoenix::arg_names; using namespace std;
int main() { boost::function<unsigned( unsigned )> factorial; factorial = if_else( _1 == 0, 1, _1 * factorial( _1 - 1 ) );
I think you'd better find a way to store factorial by reference in the phoenix expression, because the value at the time of building is empty. Totally guessing: factorial = if_else( _1 == 0, 1, _1 * ref(factorial)( _1 - 1 ) ); -- Dave Abrahams BoostPro Computing http://www.boostpro.com
On Wed, Apr 13, 2011 at 5:35 PM, Dave Abrahams <dave@boostpro.com> wrote:
At Wed, 13 Apr 2011 16:10:12 +0100, Robert Jones wrote:
I'm a newbie to Phoenix, just exploring, but I guess my intent in this code is obvious. Can anyone tell me what I'm doing wrong?
Thx
- Rob.
#include <iostream> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/statement.hpp> #include <boost/function.hpp>
using namespace boost::phoenix; using namespace boost::phoenix::arg_names; using namespace std;
int main() { boost::function<unsigned( unsigned )> factorial; factorial = if_else( _1 == 0, 1, _1 * factorial( _1 - 1 ) );
I think you'd better find a way to store factorial by reference in the phoenix expression, because the value at the time of building is empty. Totally guessing:
factorial = if_else( _1 == 0, 1, _1 * ref(factorial)( _1 - 1 ) ); Close, but, unfortunately doesn't work like this, factorial will be evaluated eagerly this way.
The solution is: factorial = if_else( _1 == 0, 1, _1 * bind(ref(factorial), _1 - 1)); factorial needs to be bound again ... bind and ref is from boost::phoenix. This only works with V3, and not with V2. You need to use the latest trunk, or wait for 1.47.
On Wednesday, April 13, 2011 05:10:12 PM Robert Jones wrote:
I'm a newbie to Phoenix, just exploring, but I guess my intent in this code is obvious. Can anyone tell me what I'm doing wrong?
Thx
- Rob.
#include <iostream> #include <boost/spirit/include/phoenix_core.hpp> #include <boost/spirit/home/phoenix/operator.hpp> #include <boost/spirit/home/phoenix/statement.hpp> #include <boost/function.hpp>
using namespace boost::phoenix; using namespace boost::phoenix::arg_names; using namespace std;
int main() { boost::function<unsigned( unsigned )> factorial; factorial = if_else( _1 == 0, 1, _1 * factorial( _1 - 1 ) );
cout << factorial( 3 ) << endl;
return 0; }
DISCLAIMER: The following is undocumented, might not work and is subject to change without notice. Phoenix V3 (from trunk) has experimental support for recursing into itself: #include <boost/phoenix/core.hpp> #include <boost/phoenix/scope/this.hpp> #include <boost/phoenix/statement.hpp> #include <boost/phoenix/operator.hpp> #include <boost/phoenix/scope.hpp> #include <boost/function.hpp> #include <iostream> int main() { using boost::phoenix::_this; using boost::phoenix::arg_names::_1; boost::function<unsigned(unsigned)> factorial = if_else( _1 <= 1 , 1 , _1 * _this(_1 - 1) ); std::cout << factorial( 3 ) << std::endl; } Have fun playing with it ;) I don't accept bugfixes for this feature cause i know it is not working in every case ... still needs a little work. If you encounter compile errors, add some dummy phoenix expression at the end of the recursing branch.
On Wed, Apr 13, 2011 at 8:04 PM, Thomas Heller <thom.heller@googlemail.com>wrote:
Phoenix V3 (from trunk) has experimental support for recursing into itself: #include <boost/phoenix/core.hpp> #include <boost/phoenix/scope/this.hpp> #include <boost/phoenix/statement.hpp> #include <boost/phoenix/operator.hpp> #include <boost/phoenix/scope.hpp>
#include <boost/function.hpp>
#include <iostream>
int main() { using boost::phoenix::_this; using boost::phoenix::arg_names::_1;
boost::function<unsigned(unsigned)> factorial = if_else( _1 <= 1 , 1 , _1 * _this(_1 - 1) ); std::cout << factorial( 3 ) << std::endl; }
Have fun playing with it ;) I don't accept bugfixes for this feature cause i know it is not working in every case ... still needs a little work. If you encounter compile errors, add some dummy phoenix expression at the end of the recursing branch.
Thanks Thomas - It's sufficient to know that what I'm trying to do is a basic limitation of the library. Cutting edge experimental stuff is fun for me, but not really an option at work! Cheers, Rob.
participants (3)
-
Dave Abrahams
-
Robert Jones
-
Thomas Heller