Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-08-13 14:14:32


>From: "Mat Marcus" <mmarcus_at_[hidden]>

>--On Monday, August 12, 2002 6:35 PM -0700 Andrei Alexandrescu
><andrewalex_at_[hidden]> wrote:
>
>> "Terje Sletteb¯" <tslettebo_at_[hidden]> wrote in message
>> news:153001c24071$34b897b0$60fb5dd5_at_pc...
>>> Take one of the simplest algorithms, factorial.<
>>> template<class V>
>>> struct factorial
>>> {
>>> typedef typename V::type Value;
>>>
>>> typedef typename apply_if<equal_to<Value,value<Value,0> >,
>>> value<Value,1>,
>>> mul<Value,factorial<prev<Value> > >
>>> > ::type type;
>>> }
>>
>> Besides, I frankly find the code abominable. It attempts to
>> look and feel like runtime C++, and to me it doesn't do it.
>>
>[snip]
>>
>> [I will snip the long explanation you provide for the
>> *simplest* example, factorial, implemented in MPL. Using some
>> of MPL. Using some not yet defined parts of MPL. Using some
>> novel ideas of your own. Using a hard to follow syntax. I
>> repeat, if that's the *simplest* example, we're really in bad
>> shape here.]

>First some meta-thoughts (regarding this discussion):

>1) There is one thread about whether or not MPL's design
>decision to offer multiple sequences is worth the cost.

>2) There is another sub-thread which is about metaprogramming
>style. This is the raw pattern matching (specialization) versus
>higher order metafunctional programming argument. This
>which-is-truer-to-the-spirit-of-functional-programming part of
>this argument is getting old, especially with the accompanying
>rhetoric ("abominable", "really in bad shape", etc.). Not to
>mention that we've been here before.

>The answer to question 1 is not entirely clear to me. Regarding
>2, I would allow for both styles. I find the writing of all the
>specializations to be somewhat tedious, repetitive and error
>prone.

That's what I've found, too. Especially if you need more advanced
terminating conditions (typical of generic algorithms such as this), where
simple pattern matching specialisations doesn't handle it.

>So I try to avoid them by using higher order
>metafuntions such as fold. I believe that sometimes this can
>result in more compact, readable code. A while ago on this list
>I tried rewriting Loki's GenLinearHierarchy using fold. It
>looked something like this (untested):

Yes, I read that posting. I didn't find that version when searching for it
now, though, only a longer implementation of GenScatterHierarchy. Aleksey
and Dave also gave versions of GenLinearHierarchy and GenScatterHierarchy,
that were shorter than the Loki version, in other postings
(http://aspn.activestate.com/ASPN/Mail/Message/1166679) and
(http://aspn.activestate.com/ASPN/Mail/Message/1166664). These were
implemented like you show here.

At that point, I felt the discussion was turning around, because here were
examples of something that was both shorter, and arguably simpler, once you
know MPL, than the Loki versions.

Up until then, there had mostly been claims of increased power, due to
abstractions, for MPL, but here we had something that was arguably simpler,
as well.

>template <class TList, class Glue, class Root = EmptyType>
>struct GenLinearHierarchy {
> typedef boost::mpl::fold<TList, Root, Glue>::type type;
>};

It may be written even shorter, as shown in Aleksey's posting above:

template< class Types, class Unit, class Root = mpl::none >
struct GenLinearHierarchy
    : mpl::fold<Types,Unit,Root> {};

That's it - three lines

>compare with the pattern matching style (from MC++D p. 72):

--- Start ---

template <class TList, template <class AtomicType, class Base>
           class Glue, class Root = EmptyType>
class GenLinearHierarchy;

template <class T1, class T2, template <class, class> class
Glue,
            class Root>
class GenLinearHierarchy<TypeList<T1,T2>, Glue, Root>
  : public Glue <T1, GenLinearHierarchy<T2, Glue, Root> >
{
};

template <class T, template <class, class> Glue, class Root>
class GenLinearHierarchy<TYPELIST_1(T), Glue, Root>
  : public Glue <T, Root>
{
};

--- End ---

Calling the first version "abominable" is in my opinion backwards. So does
it appear to be for several others following this thread.

>The point is that I prefer not to write the template and the
>two specializations. These specializations get repeated over
>and over to detect the end of a type list. Higher order
>metafunctions like fold abstract this repetition. This is not
>to say that one should never pattern match. But I can't agree
>that such code is "abominable".

Me neither.

Although, having seen the earlier Loki/MPL discussion (months ago), the
characterisation from Andrei wasn't unexpected.

>Nor is it relying on any
>misguided analogies with runtime code, nor is it less
>functional.

True.

>Please express your opinions on these matters, but
>let's tone down the rhetoric here.

Agreed.

Regards,

Terje


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