Boost logo

Boost :

From: David Bergman (davidb_at_[hidden])
Date: 2002-08-13 11:36:34


Hej, Terje.

I am an old Haskell (and other lazy FP environments) advocate, and would
like to use a (preferably lazy) functional library in C++ for a
particular project here. Could you give me some reasons not to use FC++?

Thanks,

David

-----Original Message-----
From: boost-bounces_at_[hidden]
[mailto:boost-bounces_at_[hidden]] On Behalf Of Terje Slettebø
Sent: Tuesday, August 13, 2002 9:22 AM
To: boost_at_[hidden]
Subject: Re: [boost] Re: MPL containers and algorithms

>From: "Paul Mensonides" <pmenso57_at_[hidden]>

> From: "Andrei Alexandrescu" <andrewalex_at_[hidden]>
>
> > This example has two problems: (1) it's not a "real-world" example
because I
> > don't find myself running around and computing factorials of all
possible
> > types at compile time; (2) It doesn't justify MPL's design that
imitates
> > STL's design; (3) it really works more against your viewpoint :o).
Ok,
> > that's three problems.
>
> I run around (in circles) just computing factorials in my head. :)
>
> > That's it, 9 lines of code (7 without braces), one template, two
typedefs,
> > done. :)<
> >
> > ...relying on a ton of scaffolding, some of which doesn't even
exist! No
> > more questions, your honor. I rest my case.
>
> This is not the part that bothers me. You can use some of MPL's
facilities in
> the above example (factorial) and implement the concept in a simpler
fashion.
> For instance, you could get rid of the type abstraction if you wanted
to,
etc..
> This is just putting pieces of the MPL together and nothing is forcing
anyone to
> do that.
>
> Granted, I don't think that calculating factorials at compile time is
much
more
> than a neat trick, but the example could be extended to handle some
type
of
> numeric computation that actually is useful.

Exactly. The factorial example was deliberatly selected as a simple
example,
one of the simplest there is, typically used to introduce
metaprogramming.
It was chosen to not take the focus away from something else - the
algorithmic abstraction.

Thus, criticising this example as not being a real-world example would
miss
the target. As I said, and as you say here, you have to get the pieces
to
work, if you're going to write a larger system with them.

Besides, there hasn't been a whole lot of concrete examples in this
thread,
so I figured having something concrete to discuss could help keep the
discussion focused, and separate the real stuff from red herrings and
unproven stuff.

What I would now like to see, is, at least an outline of, an MPL without
the
iterator concept. We could then use that as a basis for discussion. For
example, what would the interface to sequences, algorithms, etc. be.
Without
this, I think it'll mostly just be the what-if's. We already have the
MPL
example. To put it the way the critics have, I have yet to see a
convincing
alternative to MPL.

To make any comparison easier, tasks to be accomplished, using the two
approaches, would also be useful.

> The most relevant problem with the example is that it has nothing to
do
with
> sequences or containers--which is the primary thing that Andrei and I
are
> debating.

Andrei also questions that example, so it was useful in itself.

> Of course, there are two other problems. This little factorial
> allows you to calculate a factorial of two compile-time constants:
(pseudo-code
> follows)
>
> factorial( constant, constant )
>
> What about these:
>
> factorial( constant, runtime-value )
> factorial( runtime-value, constant )

I understand, from your later posting, that you meant "pow" here.

What about them? We are talking about metaprogramming here, not run-time
programming. If you want to evaluate it using run-time values, then of
course the algorithm has to be run-time, as well.

This is no argument against "pow", as it's outside the scope of
metaprogramming. What's your point? And what would you suggest instead?

> The same goes for 'pow', which is more reasonable in general
programming
than
> factorial.

Actually, I understand it wasn't obvious, but apart from using factorial
as
a deliberatly simple example, I also used it because it's useful in it's
own
right. It enables you to for example calculate the trigonometric
functions,
using Taylor series, which was the primary reason I made it in the first
place. It's useful to have factorial, anyway, though.

You may wonder how to represent sin, cos, etc. in MPL? Well, see those
fixed_c (fixed point type, e.g. fixed_c<3,14159265>) and rational_c
types?
They may be used for this.

Indeed, MPL is not only about sequences. This is just the beginning...
:)

Having such floating point values, allows you to implement all kinds of
floating point functions, as well, such as the mentioned trigonometric
functions (including the inverses) pow, log, sqrt, etc.

Oh, and did I mention that the "pow" may be used for any types? :) This
means making "exp" is trivial:

template<class Value>
struct exp : pow<EValue,Value> {};

EValue could here be a floating-point representation of "e".

> > Besides, I frankly find the code abominable. It attempts to look and
feel
> > like runtime C++, and to me it doesn't do it.
>
> In a sense, it does look like runtime use of the STL, but the problems
are
all
> different. Most of it is about template indirection rather than
functionality.
>
> > >For example, if you create a new value type, like double_prec, you
can
use
> > it in the above function, unchanged. :)<
> >
> > The smilye says it all...
>
> Andrei, are you trying to say that computing a compile-time factorial
of a
> floating-point number at compile-time is not worthwhile? :)
>
> It would be possible to implement arbitrary precision arithmetic at
compile-time
> this way. --But these are all academic until such things are actually
> *necessary* to produce real runtime functionality with
metaprogramming. I
could
> implement high-precision arithmetic this way, yes, but what's the
point
unless I
> actually *need* it.
>
> > >Enough of that version.<
> >
> > Agreed :o).
>
> This is the most amusing email that I've read in days. :)

Perhaps I made it a little too easy for Andrei, here. However, I didn't
expect such a cheap point to be made from it. Or I would probably not
have
said that. It was my opinion that that version was better, for reasons
I've
shown above here. However, this is something both of you may not have
considered. Metaprogramming is not limited to integer calculation, or
using
the built-in types, only.

Yes, I used a simpler version first, that Andrei found fine. However, it
was
impossible to extend. You _could not_ make it work for anything else but
integer values. Like Aleksey has generalised MPL, after having had
similar
finidings, it appears to me that some of the criticism may come from not
realising the possibilities. Possibilities where the "simple" ways
simply
don't work.

Or result in ugly workarounds. Personally, I find having to have a
sequence
converter to be a less elegant solution, than to have a uniform iterator
interface. For the same reason I would have found it inelegant in STL,
regardless of efficiency concerns.

> We have a massive
> difference in perspective here IMO, academic vs. practical.

I'm not clear who "we" you are talking about, here. You've expressed
understanding the usefulness of algorithmic abstraction, as elaborated
on
above. Andrei still questions this. You both question the usefulness of
the
iterator concept.

My example above, that Andrei was replying to, is such an example that
you've said shows useful MPL abstractions. So who are you agreeing with,
really?

> > >Let's make one that works on int, only, first. Then we'll try to
expand
it.
> > ("try" being the operating word, here. :) ).<
> >
> > Do we ever try to expand it? I repeat, this is not a good example.
Let's
try
> > to come up with an example of code that people might actually need.
>
> More importantly, this example has nothing to do with sequences.
>
> > Anyway, the example does not justify the existence of various
containers
in
> > MPL; it only says that some of MPL's utilities are useful.
>
> >> I think it may be similar with MPL. It provides an additional
abstraction,
> > so you don't have to write the explicit specialisations, etc., but
can
write
> > code in something that may be more familar, resembling run-time
code.<
> >
> > The comparison doesn't hold. It's exactly the other way: why would
people
> > have to suffer when things can be done easier.
> >
> > Again, let's steer away from comparisons and see facts for what they
are.
>
> I agree. The MPL should be able to stand on its own without the STL
backing it
> up.

True. However, much of the reasons for the power of MPL, is the same as
the
reasons for it in STL, the abstract interface, where you're not limited
to a
specific sequence, algorithm, value type, or whatever. This is an
open-ended
framework.

> > >Well, as I understamd, MPL is being used in real-life. Dave
Abrahams
has
> > mentioned using it, for example.<
> >
> > I didn't ever say MPL isn't used or can't be used.
>
> I'd like to point out also that Loki's typelists are used in real life
also.
> Further, idioms implemented with typelists are used in real life, and
Loki
> doesn't have sequence abstraction.

> The argument doesn't fly because bad code is
> being used all over the place ( not to say that the MPL is bad code
for
what it
> is supposed to be doing! ).

I was just replying to the question for real-life examples. I didn't say
that Loki's typelists isn't used in real-life, as well. Indeed, I've
used
them in my own programs. They worked well for that. However, I'm
questioning
the extensibility of that way of doing things.

Furthermore, aren't you contradicting yourself, here? First you make the
point that Loki's typelists are being used, and then you say the
argument
(about something being used) doesn't fly, as bad code is also being
used.
Sure, but this is not an argument against a specific library. You can't
use
the use of Loki as an argument for Loki, yet deny the same argument for
MPL.
No having your cake and eat it too.

> The question is, could all of the uses of the MPL
> in Boost (in the Python lib, etc.) be recreated *without* sequence
abstraction?

Perhaps much of the current use could. However, there's the question of
the
extensibility in this approach.

As Dave Abrahams replied in a posting, he has experience with a case
where
they picked a typelist, to implement it. However, it may later turn out
that
another sequence was better. If you hardwire it to a specific sequence,
then
it's not possible to do it like this. Then you're stuck with a specific
performance characteristic, also with respect to compilers. Personally,
I
would oppose a design that didn't let me use it on the system I use,
which
is mostly Intel C++. On this system, vectors are very slow, if they work
at
all.

Regards,

Terje

_______________________________________________
Unsubscribe & other changes:
http://lists.boost.org/mailman/listinfo.cgi/boost


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