Boost logo

Boost :

From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-27 14:38:56


On Fri, Feb 27, 2004 at 05:46:26PM -0000, Andy Little wrote:
> Thanks for the Examples. Apologies for not giving more constructive feedback
> on them. I will have to spend a lot more time reading the docs to understand
> all of it.... but I am getting an inkling of what the thing is about. Maybe
> if I had to manipulate generic trees I would be keener yet. Meanwhile I
> have spent some time on it but gradually got carried away with an expression
> tree. Somewhere in the FC++ Docs is a call for applications. A calculator
> ala C++3rd Ed examples might be just what is needed as a, less abstract yet,
> working example. This is my guess at one way the FP expression might
> look(Guessing from a quick look at Haskell):

[ ExprTree example elided ]

Well, I don't have time to code up a full/exciting example along these
lines right now, but perhaps you will enjoy the code below. Lemme know
if you think a more-fleshed-out version of this would be an interesting
example.

The example makes simple "int" expression trees: there are 3 kinds of
expressions (Value, Plus, Negate). At the end I use a fold to create
two tree operations: eval() and pretty(). In main() I build this tree:
      +
     / \
    5 -
        |
        3
and evaluate and print it.

#include <iostream>
using std::ostream;
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <sstream>
using std::ostringstream;

#define BOOST_FCPP_ENABLE_LAMBDA
#include "prelude.hpp"
#include "boost/tuple/tuple.hpp"

using namespace boost::fcpp;
using boost::shared_ptr;
using boost::tuple;
using boost::tuples::element;
using boost::get;
using boost::make_tuple;

struct Expr {
   virtual ~Expr() {}
};
typedef boost::shared_ptr<Expr> E;

struct Value : Expr {
   int x;
   Value( int x_ ) : x(x_) {}
};

struct Plus : Expr {
   E x;
   E y;
   Plus( E x_, E y_ ) : x(x_), y(y_) {}
};

struct Negate : Expr {
   E x;
   Negate( E x_ ) : x(x_) {}
};

struct FoldExpr {
   template <class Tup, class E> struct sig : public fun_type<
      typename RT<typename element<0,Tup>::type,int>::result_type> {};
   template <class V, class B, class U>
   typename sig<tuple<V,B,U>,E>::result_type
   operator()( const tuple<V,B,U>& ops, E e ) const {
      if( Value* v = dynamic_cast<Value*>(&*e) ) {
         return get<0>(ops)( v->x );
      }
      if( Plus* p = dynamic_cast<Plus*>(&*e) ) {
         return get<1>(ops)( (*this)(ops,p->x), (*this)(ops,p->y) );
      }
      if( Negate* n = dynamic_cast<Negate*>(&*e) ) {
         return get<2>(ops)( (*this)(ops,n->x) );
      }
      throw "bad";
   }
};
typedef full2<FoldExpr> fold_expr_type;
fold_expr_type fold_expr;

string int2string( int x ) {
   ostringstream oss;
   oss << x;
   return oss.str();
}

int main() {
   lambda_var<1> X;
   lambda_var<2> Y;

   E e( new Plus( E(new Value(5)), E(new Negate( E(new Value(3)) )) ) );

   fun1<E,int> eval = fold_expr( make_tuple( id, plus, negate ) );

   fun1<E,string> pretty = fold_expr( make_tuple(
      ptr_to_fun(&int2string)
     ,lambda(X,Y)[ X %plus% string("+") %plus% Y ]
     ,boost::fcpp::plus(string("-")) ) ); // darn ADL

   cout << eval(e) << endl;
   cout << pretty(e) << endl;
}

-- 
-Brian McNamara (lorgon_at_[hidden])

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk