Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Open letter to Mr Stroustrup

97 views
Skip to first unread message

jacobnavia

unread,
Jun 20, 2018, 6:50:38 PM6/20/18
to
Dear Sir:
In article
https://www.theregister.co.uk/2018/06/18/bjarne_stroustrup_c_plus_plus/

you say:

<quote>
Consider the C++11 range-for loop:
for (int& x : v) ++x; // increment each element of the container v

where v can be just about any container. In C and C-style C++, that
might look like this:

for (int i=0; i<MAX; i++) ++v[i];
// increment each element of the array v

<end quote>

That surprised me... since I remember that
<quote>
All standard containers provide a size() method that returns the number
of elements they actually contain.
<end quote>

So, the "C-style C++" should be written:

for (int i=0; i<v.size(); i++) ++v[i];
// increment each element of the array v

What is wrong with this way of writing software?

1) It is very clear
2) No new construct is needed.

In your article you complain that C++ should remember a top heavy danish
ship that sank after a few minutes sailing.

True, but the C++ ship sailed a long time ago. It is this endless
complexifying of simple things that makes it so indigest for the mind.

The new syntax was supposed to be eaasy to use, but it is not, since it
introduces yet another way of specifying the same thing that you have
to remember.

And that for NO REASON... the "old" way was as good as the new one.

Obviously if you put a hard wired preprocessor symbol instead of using
the standard size() function it looks ugly. But you shouldn't have to do
that in C++...

The only reason you put that MAX symbol there, is to make it ugly. Or
you aren't aware of that function?

Of course you are but you need justifying "YAST": Yet Another Syntax
Trash that you have to remember.

Avoiding top heavy languages means cutting unnecessary, redundant
features such as this one.

Yours sincerely

Jacob Navia
Progammer

Alf P. Steinbach

unread,
Jun 20, 2018, 8:36:12 PM6/20/18
to
On 21.06.2018 00:50, jacobnavia wrote:
> Dear Sir:

Bjarne participated in this group some ten to fifteen years ago. He
continued to participate in clc++m a while longer. But today he just
isn't here, as far as I know, and clc++m is dead.
The range-based `for` loop is not added complexity.

On the contrary, it's a loop with fewer degrees of freedom and simpler
syntax.

Unfortunately it's not supported by ranges, like in Python `for
range(...):`, and while the ranges proposal has a range view that can be
used to loop over integers, that has a technical, verbose, non-intuitive
name -- that to boot has changed during the library's evolution.

So to gain the FULL benefits one has to rely on DIY support or third
party libraries.

Still, the range based `for` loop is without a doubt the loop that a
beginner should start with. It's simplest in both notation and
semantics. As long as you don't delve into the behind-the-scene things.


> The new syntax was supposed to be eaasy to use, but it is not, since it
> introduces yet another way  of specifying the same thing that you have
> to remember.
>
> And that for NO REASON... the "old" way was as good as the new one.
>
> Obviously if you put a hard wired preprocessor symbol instead of using
> the standard size() function it looks ugly. But you shouldn't have to do
> that in C++...
>
> The only reason you put that MAX symbol there, is to make it ugly. Or
> you aren't aware of that function?

To me it's obvious that Bjarne intentionally wrote valid C code, so as
to avoid having to present different examples for C and C++.

For valid C code having the array bound as a constant or variable, such
as the `MAX` here, is the common situation.

Arguing by dissecting imagined nefarious motives is fallacious.

I imagine, if this group were moderated, then one rejection reason could
very well be "goes to imagined motive".

It's in my experience an indication of trolling.


> Of course you are but you need justifying "YAST": Yet Another Syntax
> Trash that you have to remember.

Arguing by calling names is also fallacious.

I think it's valid sometimes to call a person, say, "you scumbag", or
more common in Norway, "you bag of shit", as the then Norwegian minister
of the environment Thorbjørn Berntsen called his British counterpart, to
his face. That's not an argument. It's an expression of lack of regard
and lack of respect, stating openly and clearly, helpfully, the
conditions of the social room that the other must now maneuver in.

But using such terms about a technical thing, much less meaningful.


> Avoiding top heavy languages means cutting unnecessary, redundant
> features such as this one.

You will have a hard time cutting features from any language.

Python did it, in the transition from 2.7 to 3.x, but it was a drawn out
and painful process.

Anyway, the range based `for` loop is not unnecessary and redundant;
it's my impression that it's the main workhorse of loops nowadays.


Cheers & hth.,

- Alf

Öö Tiib

unread,
Jun 21, 2018, 2:38:52 AM6/21/18
to
On Thursday, 21 June 2018 01:50:38 UTC+3, jacobnavia wrote:
>
> That surprised me... since I remember that
> <quote>
> All standard containers provide a size() method that returns the number
> of elements they actually contain.
> <end quote>

But not all provide operator[].

>
> So, the "C-style C++" should be written:
>
> for (int i=0; i<v.size(); i++) ++v[i];
> // increment each element of the array v
>
> What is wrong with this way of writing software?

It does not work with raw array. That works (since C++17) ...:

for (size_t i=0; i<std::size(v); i++) ++v[i];

... but neither works with std::set because there are no operator[].
In general I agree with your concern of complicating language
but range-based for is really generic way of linear iteration over
everything iteratable.

Bo Persson

unread,
Jun 21, 2018, 5:19:14 AM6/21/18
to
On 2018-06-21 00:50, jacobnavia wrote:
> Dear Sir:
> In article
> https://www.theregister.co.uk/2018/06/18/bjarne_stroustrup_c_plus_plus/
>
> you say:
>
> <quote>
> Consider the C++11 range-for loop:
> for (int& x : v) ++x; // increment each element of the container v
>
> where v can be just about any container. In C and C-style C++, that
> might look like this:
>
> for (int i=0; i<MAX; i++) ++v[i];
>                // increment each element of the array v
>
> <end quote>
>
> That surprised me... since I remember that
> <quote>
> All standard containers provide a size() method that returns the number
> of elements they actually contain.
> <end quote>
>
> So, the "C-style C++" should be written:
>
> for (int i=0; i<v.size(); i++) ++v[i];
>                // increment each element of the array v
>
> What is wrong with this way of writing software?
>
> 1) It is very clear

It is definitely not very clear.

You have to mention i four times, each time inviting you to write j by
mistake. Same for v, used twice.

And, of course, the typical newbie error is to write <= instead of < in
the comparison.

In that view

for (int& element : container) ++element;

looks a lot clearer to me. And also works for things other than arrays.

Having been around for 7 years it is hardly "a new construct". It is
actually two language revisions old.


Bo Persson





Manfred

unread,
Jun 21, 2018, 6:25:18 AM6/21/18
to
On 6/21/2018 8:38 AM, Öö Tiib wrote:
> On Thursday, 21 June 2018 01:50:38 UTC+3, jacobnavia wrote:
>>
>> That surprised me... since I remember that
>> <quote>
>> All standard containers provide a size() method that returns the number
>> of elements they actually contain.
>> <end quote>
>
> But not all provide operator[].
>
>>
>> So, the "C-style C++" should be written:
>>
>> for (int i=0; i<v.size(); i++) ++v[i];
>> // increment each element of the array v
>>
>> What is wrong with this way of writing software?
>
> It does not work with raw array. That works (since C++17) ...:
>
> for (size_t i=0; i<std::size(v); i++) ++v[i];
>
> ... but neither works with std::set because there are no operator[].

In fact it seems to me that the example from the article is not appropriate.
The comparison should not be between range for and a C (or C-like) loop;
Instead, it should be with respect to a C++98 loop:

for(V::iterator it = v.begin(); it.end() != it; ++it) ++(*it);

(V being the type of the container, and avoiding 'auto' just to stick
with C++98)

> In general I agree with your concern of complicating language
> but range-based for is really generic way of linear iteration over
> everything iteratable.
>
The above achieves all of that with no new construct.
The only difference is that range for is more compact.
The question is if this compactness is worth the cost of having to learn
a new construct.
Probably it is so, but still I have one objection:
The range for syntax hides /how/ the sequence is traversed - while the
traditional for loop makes it explicit that it is traversed from begin()
to end() - which is the kind of detail that may be wanted to keep evident.
[BTW this is why incidentally it allows with no overhead to specify a
reversed traversal:

for(V::reverse_iterator it = v.rbegin(); it.rend() != it; ++it) ++(*it);
with containers that support reverse iteration]

So, together with improved compactness, IMHO some piece of clarity is
also lost. I'm not saying it is not worth it, just that it doesn't come
for free.

Jorgen Grahn

unread,
Jun 21, 2018, 6:59:59 AM6/21/18
to
On Wed, 2018-06-20, jacobnavia wrote:
...
> In your article you complain that C++ should remember a top heavy
> danish ship that sank after a few minutes sailing.

The ship was Swedish, actually. It was going to be used /against/ the
Danes (this was before they started nice programming languages).

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Richard

unread,
Jun 21, 2018, 1:33:40 PM6/21/18
to
[Please do not mail me a copy of your followup]

"Alf P. Steinbach" <alf.p.stein...@gmail.com> spake the secret code
<pgertg$9q1$1...@dont-email.me> thusly:

>On 21.06.2018 00:50, jacobnavia wrote:
>> Dear Sir:
>
>Bjarne participated in this group some ten to fifteen years ago. He
>continued to participate in clc++m a while longer. But today he just
>isn't here, as far as I know, and clc++m is dead.

Yeah, I don't know why he thinks this barely read newsgroups is the
place to respond to Stroustrup.


>You will have a hard time cutting features from any language.
>
>Python did it, in the transition from 2.7 to 3.x, but it was a drawn out
>and painful process.

...and my impression is that Python3 uptake is a long, slow slog.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

woodb...@gmail.com

unread,
Jun 21, 2018, 3:37:36 PM6/21/18
to
Due to their compact form, range `for` loops are useful from
an on-line code generation standpoint. The C++ Middleware
Writer requires users to have a compiler that supports them.


Brian
Ebenezer Enterprises
https://github.com/Ebenezer-group/onwards

jacobnavia

unread,
Jun 21, 2018, 5:29:55 PM6/21/18
to
Le 21/06/2018 à 19:33, Richard a écrit :
> [Please do not mail me a copy of your followup]
>

OK. I didn't.

> "Alf P. Steinbach"<alf.p.stein...@gmail.com> spake the secret code
> <pgertg$9q1$1...@dont-email.me> thusly:
>
>> On 21.06.2018 00:50, jacobnavia wrote:
>>> Dear Sir:

Well, why not?

>> Bjarne participated in this group some ten to fifteen years ago. He
>> continued to participate in clc++m a while longer. But today he just
>> isn't here, as far as I know, and clc++m is dead.

Social media appear and disappear. Usenet was the first one, and, I
still think written conversations are great for discussing general
interest stuff.


> Yeah, I don't know why he thinks this barely read newsgroups is the
> place to respond to Stroustrup.
>

Well, I do not think that's important to the discussion. Since I do not
follow the party line, if the commander in chief is here or not, it
doesn't change the discussion.

He used the example of a top-heavy ship that sank. Well, I have been
saying exactly the same thing here and in the C group.

To illustrate that, he uses in a very strange way the example I showed.

Let's see that in more detail.

<quote again>
In C and C-style C++, that might look like this:

for (int i=0; i<MAX; i++) ++v[i];
// increment each element of the array v
<end of the repeated quote>

This statement can be written in C++, using the old syntax.

I wrote:

So, the "C-style C++" should be written:

for (int i=0; i<v.size(); i++) ++v[i];
// increment each element of the array v

What is wrong with this way of writing software?

1) It is very clear
2) No new construct is needed.


Some objections were raised, for instance that plain arrays wouldn't
work, they do not have a size() method.

Strange. C++ doesnt have something? Hard to believe...

Well, obviously a top-heavy ship needs a more broad base to be able to
support that so heavy top. C++, like C, doesn't have an array type and
plain arrays are stored without size information.

Instead of solving THAT problem C++ develops a way of hiding it under
the carpet of a new syntax for "containers".

One of the oldest containers is precisely the array TYPE. An easy to
learn and use array type would be nice, isn't it?

Plain arrays are stored with size information and the .size() method
works for them too.

As for any container.

General rules simplify the language. Arrays are objects like others, and
can answer simple requests like size() and maybe others.

This doesn't affect the speed of the generated code since array access
isn't at all modified, and the syntax is kept the same. The array type
would be plain arrays

jacobnavia

unread,
Jun 21, 2018, 5:49:34 PM6/21/18
to
Le 21/06/2018 à 08:38, Öö Tiib a écrit :
>> What is wrong with this way of writing software?
> It does not work with raw array. That works (since C++17) ...:
>
> for (size_t i=0; i<std::size(v); i++) ++v[i];
>
> ... but neither works with std::set because there are no operator[].

If there is no operator[] that should be a compile time error of course.

But what are you doing when incrementing each element of a set?

A set... maybe you just mixed up something?

Coming back to the original discussion, what I do not understand is why
you have to write:

std::size(v)

instead of

v.size()

????

The foundations must be broader to accomodate that heavy top, I repeat.

Why v.size() doen't work?

If we store size information together with the array, we can get at run
time the size of the array.

For instance we could set a class of arrays, using plain arrays as a
base of a more rational approach to bounds checking, run time
optimizations, and other things.

You can at run time choose some algorithm for small matrices that
doesn't scale but is great for small data sets using the size information.


jacobnavia

unread,
Jun 21, 2018, 6:12:33 PM6/21/18
to
Le 21/06/2018 à 11:19, Bo Persson a écrit :
> It is definitely not very clear.
>
> You have to mention i four times, each time inviting you to write j by
> mistake. Same for v, used twice.
>

Sure.

You can do a typing mistake.

Do we need new syntax to avoid typing mistakes?

The new syntax must be learned and remembered by all users of the language.

The typing mistake is easily fixed, in most cases. And please consider:

for (int& elemnt : container) ++element;

is just as wrong...

:-)

> And, of course, the typical newbie error is to write <= instead of < in
> the comparison.
>

Sure. Newbies make all kinds of mistakes. Should a new syntax be
introduced that is newbie-proof???

> In that view
>
>   for (int& element : container) ++element;
>
> looks a lot clearer to me. And also works for things other than arrays.
>

The index variable is now lost. How is this thing iterated? A whole new
syntax must be learned to subclass this thing by specifying a range,
what is not very easy and means YET ANOTHER thing to learn. The specs
are complicated, see for instance:
https://en.cppreference.com/w/cpp/experimental/ranges/range/Range

And those ranges are supposed to be continuous. How do you do a set of
elements like "pair numbered" ?

You want to specify a filter? Learn how ranges are constructed and used
in the new syntax. Forget about:

for (int i=0; i<MAX; i++)
if (i&1) continue; // Treat only pair numbered pixels

You can here easily specify filters without learning any new syntax.

But that is "C like" and obsolete.

> Having been around for 7 years it is hardly "a new construct". It is
> actually two language revisions old.

Yes, C++ programmers are used that there is each 2-3 years a bunch of
new syntax to learn. Fancy constructs where you learn to do the same
things with new syntax.

jacobnavia

unread,
Jun 21, 2018, 6:23:44 PM6/21/18
to
Le 21/06/2018 à 21:37, woodb...@gmail.com a écrit :
> Due to their compact form, range `for` loops are useful from
> an on-line code generation standpoint.

If you are generating code, the difference between generating a slightly
longer ascii output or a shorter one is meaningless.

Öö Tiib

unread,
Jun 22, 2018, 1:14:33 AM6/22/18
to
On Friday, 22 June 2018 00:49:34 UTC+3, jacobnavia wrote:
> Le 21/06/2018 à 08:38, Öö Tiib a écrit :
> >> What is wrong with this way of writing software?
> > It does not work with raw array. That works (since C++17) ...:
> >
> > for (size_t i=0; i<std::size(v); i++) ++v[i];
> >
> > ... but neither works with std::set because there are no operator[].
>
> If there is no operator[] that should be a compile time error of course.
>
> But what are you doing when incrementing each element of a set?
>
> A set... maybe you just mixed up something?

Yes, good catch! Set elements aren't mutable so can't increment. Others
like std::list also do not have [].

> Coming back to the original discussion, what I do not understand is why
> you have to write:
>
> std::size(v)
>
> instead of
>
> v.size()
>
> ????

The raw array does not have methods. It decays to pointer and so works
with operator [] of pointer. Therefore in templates (or when generating
code in some other way) std::size works bit better.

> The foundations must be broader to accomodate that heavy top, I repeat.
>
> Why v.size() doen't work?
>
> If we store size information together with the array, we can get at run
> time the size of the array.
>
> For instance we could set a class of arrays, using plain arrays as a
> base of a more rational approach to bounds checking, run time
> optimizations, and other things.
>
> You can at run time choose some algorithm for small matrices that
> doesn't scale but is great for small data sets using the size information.

That is implemented in std::array. It has efficiency of raw array but
usage of library container. The a.size() is compile time constant.

Öö Tiib

unread,
Jun 22, 2018, 1:38:23 AM6/22/18
to
On Thursday, 21 June 2018 13:25:18 UTC+3, Manfred wrote:
>
> In fact it seems to me that the example from the article is not appropriate.
> The comparison should not be between range for and a C (or C-like) loop;
> Instead, it should be with respect to a C++98 loop:
>
> for(V::iterator it = v.begin(); it.end() != it; ++it) ++(*it);
>
> (V being the type of the container, and avoiding 'auto' just to stick
> with C++98)

Yes. Also because of lack of lambdas the C++98 algorithms were harder
to use and so C++98 code was often full of those for's.


> The above achieves all of that with no new construct.
> The only difference is that range for is more compact.
> The question is if this compactness is worth the cost of having to learn
> a new construct.
> Probably it is so, but still I have one objection:
> The range for syntax hides /how/ the sequence is traversed - while the
> traditional for loop makes it explicit that it is traversed from begin()
> to end() - which is the kind of detail that may be wanted to keep evident.
> [BTW this is why incidentally it allows with no overhead to specify a
> reversed traversal:
>
> for(V::reverse_iterator it = v.rbegin(); it.rend() != it; ++it) ++(*it);
> with containers that support reverse iteration]
>
> So, together with improved compactness, IMHO some piece of clarity is
> also lost. I'm not saying it is not worth it, just that it doesn't come
> for free.

I have noticed that the (unimportant at that point) details may damage
clarity. For example exceptions are better for error handling than error
codes because those let us to have constructors and operators that can
fail. Handling of the failed cases is moved to catch block (or down
the call stack) and so the clarity of code that deals with normal case
is improved.

Bo Persson

unread,
Jun 22, 2018, 5:08:49 AM6/22/18
to
On 2018-06-22 00:12, jacobnavia wrote:
> Le 21/06/2018 à 11:19, Bo Persson a écrit :
>> It is definitely not very clear.
>>
>> You have to mention i four times, each time inviting you to write j by
>> mistake. Same for v, used twice.
>>
>
> Sure.
>
> You can do a typing mistake.
>
> Do we need new syntax to avoid typing mistakes?
>
> The new syntax must be learned and remembered by all users of the language.
>
> The typing mistake is easily fixed, in most cases. And please consider:
>
> for (int& elemnt : container) ++element;
>
> is just as wrong...

Yes, this will likely cause a compile error. The problem with i and j in
nested loops is that the code will often compile, even if you mix them
up badly.

for (int i = 0; i < matrix.size(); i++)
for (int j = 0; j <= matrix[j].size(); i++) // OOPS * 3!
cout << matrix[i][j];

vs

for (auto& row : matrix)
for (auto col& : row)
cout << col;

Which one is easiest to learn? And easiest to get right?




Bo Persson

Bo Persson

unread,
Jun 22, 2018, 5:11:28 AM6/22/18
to
And this does give you a compile error when you place the & wrong. Still
not perfectly simple, apparently :-)


>
>
>
>     Bo Persson

0 new messages