Boost logo

Boost :

From: David A. Greene (greened_at_[hidden])
Date: 2001-12-13 17:47:52


Mat Marcus wrote:

> add. First, I should mention that this code was not meant to be the
> definitive version of GenScatterHierarchy.

Right. However, I think examples of MPL usage should be kept
simple. It's not helpful to new users to see a big complex
composition of metafunctions first thing in the morning. :)

> Yes, the _1 placeholder variable needs further exploanation. Just as
> in Jaako and Gary's lambda library the underscored variables represent
> the parameters to the metafunction. At each iteration _1 will be bound
> to the element from the container. See
> <http://www.oonumerics.org/tmpw01/jarvi.pdf> for a good discussion.

I got that bit. But _1 was also passed to the next<>...erm...what's
the name for it? :) I don't know if that means "add 1" or something
else. I'm thinking back to Aleksey's explanations of int_t and
how they have both a type and a value.

> understanding of STL. I am reasonably comfortable with
> std::accumulate and after an initial learning curve I find the
> following metacode to be analagous:
>
> template <class TList, class Unit, class Root = EmptyType>
> struct GenLinearHierarchy {
> typedef boost::mpl::for_each<
> TList // container
> , Root // intial state
> , Unit // BinaryFunction
> >::state type;
> };

I think the naming of "for_each" got me. "accumulate" makes much
more sense. for_each doesn't imply a carryover of state like
accumulate does.

> Compare this with:

[A recursive implementation]

> Perhaps it's because I don't spend enough time with functional
> programming languages, but as a C++ programmer by trade I can read and
> write metacode in the first style more rapidly then the second.

The multiple composers, binders and metafunctions really threw
me for a loop. The second style makes sense to me because
typelists are defined recursively. It makes sense to me that
a hierarchy would be defined recursively because inheritance
is "recursive" in that it takes a tree form in the general
case.

After explanations from Dave and Aleksey I am more comfortable
with the iterative approach but I still don't understand it
completely.

> One thing I noticed when porting Loki typelists was that there was
> quite a bit of repetition in the pattern matching. In the original
> code there are often three cases: a general typelist case, an atomic
> case, and a null case. Though this form of pattern matching offers a
> kind of functional purity/elegance, in some cases one might argue that
> this is simply a long winded way of expressing the desire to visit
> each element in a typelist.

Yes, I have also noticed the three-case pattern and have wondered
about it. Is it a general requirement for that style of
metaprogramming? I've seen it pop up in my own experiments
with code altogether unrelated to hierarchy generation.

> BTW, another interesting side effect of this implementation is that the
> resulting scatter hierarchy has fewer intermediate classes (see the
> diagram on page 66 of MC++D). This is also true for the linear
> hierarchy.

There is something to be said for that, though Dave's example
of what Aleksey's implementation would do to class names was
rather...disturbing. :)

> Mark> As for non-portability, it's not correct to call something
> Mark> non-portable because some compilers are broken. Blame the

>
> Fair enough. What I'm really getting at is that I really want to use
> this stuff today, not in two+ years when most people will have
> standardized on compilers that are up to the job.

Entirely reasonable. However, "non-portable" carries a rather
negative connotation that is not applicable to code techniques
that are guaranteed by the standard to work.

> Mat > * "Dynamically" compose metafunctions with compose_f_gxy
>
> Mark> In your examples the use of composition is not at all
> Mark> obvious.
>
> Forgive me. This is only a midnight hobby after all :-) I think Dave
> answered this in his post. I will add one comment. I really like the
> STL lambda example that Jaako and Gary give in their 2001 Template
> metaprogramming Workshop paper (see URL above):

I'll look at it. Thanks!

> //With a lambda facility the above code becomes much simpler:
> transform(angles.begin(), angles.end(),
> sines.begin(),
> - bind(sin, _1 * pi / 180.0));

Much, much better, clearly. I hope we get more of this type of
stuff in Boost. Is the Lambda Library going to be submitted
for Boostification?

> MPL already has simple placeholders (_1 and _2) and I expect that a
> lambda facility for MPL could alleviate the need for compose.

I would like to see this along with examples.

> Mat > * MPL does not rely on template templates or partial
> Mat > specialization. It does a pretty good job encapsulating
> Mat > compiler limitations. Of course metaprogramming VC 6/7 remains
> Mat > somewhat nightmarish, and the port here is still not complete.
>
> Mark> What exactly is nightmarish?
>
> I assume you are joking here.

No, no, I was asking for examples. I have no doubt it's
nightmarish. :)

> Mark> I don't think it's fair to knock Loki because it wasn't
> Mark> coded with broken compilers in mind.
>
> By the way I'm not knocking Loki. I think Loki is cool. As I mentioned
> above, I don't want to wait two years until we move to an adequate
> compiler; I want to use it today. I am just trying to focus our Loki,
> MPL discussion.

I'm glad you did. We need examples like the one presented by
you, Dave and Aleksey. I'd like to see the patterns in MC++D
implemented with MPL so we can compare them. Feel free to
post them, debate and generally beat them into shape because
Andrei got to do multiple iterations of his implementations. :)

By "knocking Loki" I meant describing its techniques as non-portable
when they are not.

> Mark> You work shows that it is possible to maintain a nice
> Mark> recursion interface while still achieving working code on
> Mark> such platforms.
>
> Thanks. But I'm not sure I understand what you mean by a recursion
> interface? The interface to the hierarchy generators is more or less
> unchanged. Do you mean recursive implementation.

Yes, right. Sorry about that. Fuzzy brain syndrome. :)

> endlessly. While the applicitave for_each style may take some learning
> I believe that it is a useful way to factor out common code, just as
> stl::for_each offers a way to visit each element in a sequence.

I'm sure it can be. I need more examples and comparisons to know
when it is appropriate to use and when not.

                             -Dave

-- 
"Some little people have music in them, but Fats, he was all music,
  and you know how big he was."  --  James P. Johnson

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