Boost logo

Boost :

From: Terje Slettebø (tslettebo_at_[hidden])
Date: 2002-08-11 15:34:55


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

>From: "Terje Slettebø" <tslettebo_at_[hidden]>

> > Also, a newcomer has an easier learning curve to template
metaprogramming
> and
> > how it works in the general sense--rather than the use of a specific
> > library--Loki or the MPL.
>
> By all means, learning how it works is useful, too. However, I don't think
> we should repeat the mistake that some C++ teachers do, to teach C++ the
way
> themselves learned it, going the C-first way, if there there turns out to
be
> a better way of learning it, learning C++ as a high-level language, by
> _starting_ with using the library, rather than having that towards the end
> of the book, as is often common.

>I don't think that you can say unilaterally that learning C++ with the "C
>subset" is a mistake.

Just accentuating it a little. :) I've been through that kind of course,
although I had learned C++ earlier. However, I saw the effect of it on the
students, who were struggling with low-level C concepts, such as char *
instead of std::string.

Anyway, you're right.

>Doing that presents dangers, yes, but so does teaching
>high-level functionality first. Any one that is commited to actually
learning
>C++ will learn it fine either way.

Yeah. :)

>> I learned C before C++, too, and I used to think it was the best way. I
>> don't, anymore. The authors of "Accelerated C++" also have experience
with
>> both ways of teaching it.
>
>Yes, and we also have the results of the high-level style of teaching as
well.
>Lots of programmers can put pieces together, but not enough of them know
what is
>actually going on--even in a general sense. They don't understand the
actual
>way that computers work or any of the low-level details.

Yes. I've certainly found it useful myself, to know how things actually
work. Thus, both kinds of knowledge is useful.

I think it's just a matter of what you want to teach. In the mentioned
course above, it was the only C++ course at college, a half-year course in
the third and last year (!) The rest was Java. If the aim was to teach good
programming in C++, I think they may have got further going the high-level
way. There was no STL, and hardly any of the standard library.

After all, I didn't start with C, and char *, either. I started with BASIC.
Since it has high-level constructs, such as strings, it let me get a gentle
introduction to programming.

Later, it became Pascal, C, C++, Java, and assembly. :) By the way,
curiously enough, metaprogramming reminds me of assembly, which is part of
my attraction to it, I guess. It's an "uncharted territory".

I've earlier worked on an ARM assembler
(http://student.iu.hio.no/~slettet/eng/extasm.html), which is written in ARM
assembly, itself. This included writing the expression engine for it. It
became quite sophisticated, including most of the integer, floating point,
and string operations found in BBC BASIC, :) as well as auto-conversions
between these.

Now, assembly isn't much used, as a compiler typically performs better than
a programmer at optimising. So now, we have all these functions already
available.

However, with the advent of metaprogramming in C++, we essentially have a
new language, where things can be written. :) The "pow" function wouldn't be
much point in making in run-time programming, as it already exists, there.
However, for compile-time programming, building up such components is kind
of virgin territory, again. That makes it exciting. :)

By the way, my experience with courses, like the above, and the general
level of the teachers, makes me glad I'm mostly self-taught. :)

>> The same may go for metaprogramming. I also learned the template
>> specialisation, pattern-matching way first. Much of what I know about
>> metaprogramming, especially the practical application of it, I've learned
>> from "Modern C++ Design". So that certainly has much credit for it.
>>
>> Similarly, it may be better to learn metaprogramming, by using a library
for
>> it, rather than starting with writing your own components.
>
>Of course, I was simply saying that using a library will only help you 1)
do
>what the library already does and 2) learn metaprogramming concepts and
techniques.
>If the library fails to do that later, than you are ill-equipped to extend
>the library or make your own constructs.

You can also learn the fundamentals, without the library. After all, you
don't need STL to teach you C++.

>> > > > In fact, MPL code resembles more run-time code, than Loki's
typelists,
>> > > which
>> > > > means that you can use your experience with such code, when using
it.
>> > >
>> > > Agreed.
>> >
>> > Agreed as well, _however_ template metaprogramming is a different
>> environment
>> > altogether. You are simply hiding the natural way that environment
works
>> with
>> > constructs that can only imitate imperative programming. This is not
>> > _completely_ bad, but it does have disadvantages as well. At some
point,
>> a user
>> > is going to run into the full, actual environment that is template
>> > metaprogramming with no analogy to STL to help (i.e. coddle) them
along.
>>
>> The same has been said about using C++ as a high-level language, to
advacate
>> for teaching the low-level C details first. However, it has been found
that
>> you _can_ use std::string, the STL, etc. as high-level components,
without
>> having to learn how they actually work.
>
>Yes, but just like teaching low-level details first, this is a time-bomb
waiting
>to explode. I'll go out on a limb here :) and say that for someone who is
>actually interested and actively committed to learning C++, it doesn't
matter
>which way they learn first. For someone interested only in turning out the
>required functionality, what you say is true. However, I don't really care
>about people that don't care to learn C++ fully.

There are a couple of issues, here (although this strays some from the
topic, MPL). Yes, you may learn C++ either way, or any way. As you say, each
way has its consequences.

If we take the first step, first:

People who learn the C-first way will learn well about how it works,
fundamentally, including how the computer works, quite much. People who
learn the high-level first will learn the concepts and abstractions well.

Then we go to the transition, learning the respective other part:

People in the first group, now learning the high-level stuff and
abstractions, may have to "unlearn" some C ways, to be able to write good
C++. However, this is true for any language transition. Myself, I spent a
little while using C++ as a "better C", before I grasped this about OO,
generic programming, etc.

People in the second group, if they don't learn the fundamentals, low-level
stuff, too, may write inferior programs, because they don't know what
happens under the covers. They may have a similar transition - this time,
trying to map the high-level to the low-level (rather than the other way for
the first group).

In summary, these are just some observations.

However, if people only learn some C++, they may be able to write better
C++, by going the high-level way first, than the C-first way, which may
leave them as almost only knowing the C-part of the language. If these
people go out to write software, then I think you'd find that the first
group tended to write better C++, because they use the higher abstractions,
and are thus kept mostly out of trouble, than if they were to use
insufficient knowledge to do relatively advanced stuff, such as memory
management.

To take an example of this, in the mentioned course, one of the assignments
were to write a matrix class. The teacher's suggested solution used
dynamical memory allocation (rather than e.g. basing it on an STL
container), and would leak as a sieve in the presence of exceptions. The
same was the case for the student answers. Yes, writing exception-safe code
is hard. Which is why they could instead used STL, and written good code.

>> As mentioned in the previous posting, the basic difference between the
two
>> is binding time. That's all. The rest is about how it's implemented. For
>> run-time programming, the means are the run-time constructs, and for
>> compile-time programming, the means are the compile-time constructs. The
>> ends may well be the same.

>No, binding time is obviously relevant, but the basic difference is not
binding
>time. Metaprogramming produces code (in a sense) to be consumed by the
regular
>code. That is a big difference.

Well, perhaps one could call it time of executioon, instead. As you say,
this is then used by the run-time.

>> > He means, I think, using imperative types of abstractions (such as
>> iteration vs.
>> > recursion, etc.) in a functional environment. In a sense he is right.
>> _But_ we
>> > have decades of experience with imperative and functional languages
that
>> say one
>> > thing or another is not a _natural_ idiom in a functional language. We
>> better
>> > be pretty sure of ourselves to throw out the learning gained in the
past.
>>
>> Let's be concrete, what in MPL would be an example of what you say here?
>> That is, expressing something that isn't found in FP, and which would be
>> different to "traditional" MP.
>
>Iteration vs. recursion for example. The styles involved in functional
>programming are inherently different than imperative programming in many
>respects. Template metaprogramming is functional, therefore the most
natural
>way to use such a language is with the functional style that has been built
over
>many years.

Some functional constructs are also found in MPL, such as iter_fold,
precisely for this reason, as I understand.

However, just as you can do functional programming in an generally
imperative language like C++ (like using a library like FC++), then you can
also use other ways in an FP system like C++ MP.

Are you saying that you think it would be better with only FP constructs in
MPL? That would mean no iterators (I guess), and it might mean that you
loose the familiarity from run-time programming. It would mean a large
change, when going from one to the other. This is just what MPL tries to
avoid, by instead presenting familiar constructs. This way, the transition
may be smoother. This was also a point in the "Static Data Structures" paper
that Doug mentioned.

>> > to the use of multiple sequence types? IMO, the correlation to the STL
>> breaks down at this point.
>>
>> Sequences is just one thing. Combination of metafunctions, lambda (not
found
>> it STL, but found in Boost.Lambda), etc. are also similar.

>The STL analogy applies specifically to sequences.

Well, look deeper: "plus", "minus", "multiplies", "divides", function
composition, etc. All parts of STL, as well. MPL resembles STL + BLL.

>I don't mean that the MPL
>has stuff that the STL doesn't or vice-versa. I mean that the fundamental
>premise of the STL analogy is flawed with regard to sequences because the
actual
>reasons for that abstraction in the STL do not apply to template
>metaprogramming. The only thing that you really get out of it is syntactic
>sugar and limited similarity to STL code--which is not nearly as strong of
an
>argument as you tend to make it (IMHO). :)

Did you read my reply to Andrei, where I presented the generic "pow"
routine, and its run-time counterpart?

This had nothing to do with sequences at all, and that was deliberate.
Instead, it showed the power of abstraction in MPL, which lets you use the
same algorithm for any type that satisfies the concepts. This is _precisely_
the same way it is in STL.

I suggest you look again.

I haven't gone as strongly on the sequences-similarity to STL, but instead
emphasisted the generic qualities. However, I find the iterator concept to
be powerful in itself, in that it decouples sequences from algorithms.
Regardless of efficiency issues, this is powerful in itself. It means that
if you create a new sequence, you can use it with existing components.

To take the last you say:

>The only thing that you really get out of it is syntactic
>sugar and limited similarity to STL code--which is not nearly as strong of
an
>argument as you tend to make it (IMHO). :)

I understand you here talk about sequences, specifically, and not MPL in
general. Where have I made this as such a big point, you say? I, and others,
have said that the decoupling of sequences from algorithms may be useful in
itself. In what way have I "tended to make this a strong argument"? I've
said that measurements could give us more info about this. And that's
something we have got now. I don't recognize my postings in what you say,
here.

Regards,

Terje


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