$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Andrei Alexandrescu (andrewalex_at_[hidden])
Date: 2002-04-13 12:09:48
"Vesa Karvonen" <vesa_karvonen_at_[hidden]> wrote in message
news:F289vDzPfYYXp0hFlJl0000d048_at_hotmail.com...
> Aleksey Gurtovoy:
> >Joel de Guzman:
> > > > Are you familiar with functional programming?
> > >
> > > What's the point of this question? To gauge my level of
competence
> > > to form an opinion?
> >
> >No, not at all. I just didn't want to reveal the second question
> >before you answer the first one :). The argument about "simplicity"
of
> >pattern-matching-self-recursive-partial-specialized 'count_if'
> >implementation is partially built around the assumption that it's
easy
> >to understand for somebody with functional programming background.
To
> >me, functional programming primitives like 'fold' et al. seem much
> >more important concepts than any esoteric low-level patterns
matching.
>
> FWIW, IMO, Aleksey is right here, and people who don't understand
the
> purpose of higher order sequence manipulation functions should
really read
> some book on functional programming.
Higher order sequence manipulation functions are indeed important.
Where I think otherwise is the simplicity argument.
IMHO, understanding matching for template arguments in the context of
C++ does not ask for a functional programming background. It asks for
C++ background. Template arguments are matched to template parameters,
and this is a fact of C++. This C++ feature can be useful in a number
of contexts.
My argument on the simplicity of the pattern-matching implementation
of count_if is NOT based on the assumption that people with functional
programming background would be comfortable with it. (I am not much of
a functional programmer myself.)
The implementation of count_if as a library artifact is largely
irrelevant. As long as a library function respects an interface, the
library user can only appreciate a more sophisticated implementation.
I understand we are discussing count_if as an example of typical
implementation of a user-defined algorithm.
Again, let me post some simple measurements of the two variants of
count_if.
The count_if implementation using mpl has 34 lines, defines 3 new
types, 1 new namespace, and relies on 5 artifacts defined elsewhere.
The count-if that works only for dot-typelists has 15 lines, defines 1
new type, and does not rely on any other artifacts than the typelist
itself.
This being said, my argument on the simplicity of the pattern-matching
implementation of count_if is based on the following points:
1. Show the sheer code to a C++ programmer. For completeness' sake, I
appended the code at the end of this post.
2. 15 < 34
3. 1 < 3
4. 0 < 1
5. 1 < 5
Several people have repeatedly asked for self-contained, sensical
examples demonstrating that using the style pioneered by MPL leads to
a good solution. I believe this is reasonable to ask for.
Andrei
--
Appendix:
---------------
Version of count_if using MPL's facilities
---------------
namespace aux {
template< typename Predicate >
struct next_if
{
template<
typename N
, typename T
>
struct apply
{
typedef typename select_if<
apply<Predicate,T>::value
, typename next<N>::type
, N
>::type type;
};
};
} // namespace aux
template<
typename Sequence
, typename Predicate
>
struct count_if
{
typedef typename fold<
Sequence
, integral_c<unsigned long, 0>
, aux::next_if<Predicate>
>::type type;
BOOST_STATIC_CONSTANT(unsigned long
, value = type::value
);
};
---------------
Version of count_if that works on dot-typelists only
---------------
template <class TList, class Predicate> struct count_if;
template <class Predicate>
struct count_if<Nulltype, Predicate>
{
BOOST_STATIC_CONSTANT(
unsigned long,
value = 0);
};
template <class H, class T, class Predicate>
struct count_if<typelist<H, T>, Predicate>
{
BOOST_STATIC_CONSTANT(
unsigned long,
value = (Predicate::apply<H>::value ? 1 : 0) + count_if<T,
Predicate>::value);
};