|
Boost : |
From: Brian McNamara (lorgon_at_[hidden])
Date: 2004-02-26 15:13:11
On Thu, Feb 26, 2004 at 02:39:40PM +0200, Peter Dimov wrote:
> Brian McNamara wrote:
> > The FP programmer, being enamored with higher-order functions (HOFs),
> > notices that all these tree functions have a common pattern. Rather
> > than write tons of miscellaneous tree functions, he instead writes one
> > function to do them all:
> >
> > // using FC++
> > struct FoldTree {
> > template <class L, class N, class SPT>
> > struct sig : public fun_type<L> {};
> > template <class L, class N, class T>
> > L operator()( const L& leaf, const N& node,
> > shared_ptr<Tree<T> > t ) const {
> > if( !t )
> > return leaf;
> > else
> > return node( t->data, (*this)(leaf,node,t->left),
> > (*this)(leaf,node,t->right) );
>
> The order of evaluation is unspecified, so if the subexpressions have side
> effects, the code is not portable. But the programmer wouldn't know it if it
> happens to work on the specific platform/compiler/version/moon phase.
>
> Pure FP doesn't suffer from these problems, but C++ does. As a simple
> example, try to print a tree using fold_tree.
Yes. I think I mentioned it in an earlier message, but it bears
repeating. When you use FP, HOFs make it harder to specify and reason
about side-effects, and currying and lazy evaluation make it harder to
specify and reason about object lifetimes. These are among the reasons
the FP people usually go for purity.
> > With fold_tree(), it is easy to express new tree functions on the fly.
> > For example, here is a function to get an inorder travseral:
> >
> > fold_tree( fcpp::list<T>(), lambda(D,L,R)[ cat[ L, cons[D,R] ] ] )
>
> You got me confused for a while with the omission of the third argument. I
> then spent a while trying to understand how the lambda thing would get
> passed around. ;-)
Oops! My bad. I'm actually trying to make the examples accessible,
rather than inpenetrable. :) When you get accustommed to automatic
currying, you don't ever notice that you're using it.
> Anyway, the obvious question #1 is, of course, why should I use a fcpp::list
> instead of std::list,
Here the answer is because I'm building the the list "pure"ly,
so fcpp::list is probably much more efficient (fcpp::cons is constant
time, whereas the same operation on a std::list is potentially O(N)).
> and obvious question #2 is why I should copy the tree
> into a list at all, when I could've just flattened it into a sequence with
> iterators. To be fair, you do point that out yourself.
Good point; I was just keeping the example simple.
(In fact, when you use fcpp::lists with lazy evaluation, lists
effectively become input iterators. It would be interesting to
implement inorder-iterators for this tree both with and without FC++.
Hmm. How easy/hard would it be to build bidirectional iterators for a
tree like this? I've never tried. If you have the time to cook some up
(using Boost), I would enjoy seeing them, and comparing them to whatever I
could cook up with FC++.)
> However iterators do avoid the unspecified traversal order problem. Not
> that you couldn't have created inorder_fold_tree, of course, but
> iterators make it much harder to accidentally leave the order
> unspecified.
Time out. This:
fold_tree( fcpp::list<T>(), lambda(D,L,R)[ cat[ L, cons[D,R] ] ] )
always yields an inorder traversal. And:
// preorder
fold_tree( fcpp::list<T>(), lambda(D,L,R)[ cons[ D, cat[L,R] ] ] )
// reverse-inorder
fold_tree( fcpp::list<T>(), lambda(D,L,R)[ cat[ R, cons[D,L] ] ] )
// etc.
The lambda uses no effects, and thus the order of evaluation inside the
fold_tree() doesn't matter.
> > fold_tree( 0, lambda(D,L,R)[ plus[ 1, max[L,R] ] ] )
>
> Okay, but this is easy to do even with boost::bind. We want unique selling
> points. ;-)
I do see the smiley, but just to be abundantly clear, I was selling
HOFs ("Here's an example that shows how higher-order functions are
useful..."), and boost::bind is indeed just such an entity.
-- -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