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

Overuse of 'auto'

605 views
Skip to first unread message

Juha Nieminen

unread,
Dec 8, 2022, 7:32:04 AM12/8/22
to
During the last few years I have had to read an inordinate amount of
code written by other people. It has really given me a big insight on
what makes code more and less readable and understandable. For example,
I could write an entire book on naming conventions alone, and how they
can make the code so much more readable, or make it almost inscrutable.

But another thing I have really learned to hate is the overuse of the
'auto' keyword. I have always opposed its needless overuse, but this
couple of years of reading other people's code has really confirmed
and cemented my previous opinion on it.

Some C++ programmers do not use 'auto' merely to save some typing,
as some kind of convenience feature. They go their way to use it
pretty much everywhere they can, even when it doesn't actually save
any typing or make anything more convenient. They use it like it were
the generic variable declaration keyword in many other languages
(quite typically "var").

The problem in using 'auto' everywhere, from the perspective of someone
who is reading the code, is that it hides the type in question. When
you see something like:

auto foobar = someFunction(a, b);

it's a complete mystery what that return type is, and thus the reader
(ie. me) has no idea what it actually is, what it does, and how it's
used. Could be an 'int', could be a 'double', could be a 'std::string',
or could be a custom type declared somewhere else in the program. That
line alone doesn't clarify. Quite often even subsequent lines of code
don't necessarily clarify.

It just makes code so much harder to read when this crucial information
has been hidden from you. This is not really what "information hiding"
should be about.

"Yada yada! Just use an IDE like everybody else does!"

Even putting aside the fact that well-written code shouldn't rely on the
reader using an IDE to understand it, there are many situations where
you don't have a fancy IDE to tell you what that type is, or where it
can be found, such as for example when reading and reviewing the code
in gitlab. Try reviewing code when you can't even see what the types
being used are.

Man, have I learned to hate the overuse of 'auto'...

Bo Persson

unread,
Dec 8, 2022, 9:25:48 AM12/8/22
to
On 2022-12-08 at 13:31, Juha Nieminen wrote:
> During the last few years I have had to read an inordinate amount of
> code written by other people. It has really given me a big insight on
> what makes code more and less readable and understandable. For example,
> I could write an entire book on naming conventions alone, and how they
> can make the code so much more readable, or make it almost inscrutable.
>
> But another thing I have really learned to hate is the overuse of the
> 'auto' keyword. I have always opposed its needless overuse, but this
> couple of years of reading other people's code has really confirmed
> and cemented my previous opinion on it.
>
> Some C++ programmers do not use 'auto' merely to save some typing,
> as some kind of convenience feature. They go their way to use it
> pretty much everywhere they can, even when it doesn't actually save
> any typing or make anything more convenient. They use it like it were
> the generic variable declaration keyword in many other languages
> (quite typically "var").
>
> The problem in using 'auto' everywhere, from the perspective of someone
> who is reading the code, is that it hides the type in question. When
> you see something like:
>
> auto foobar = someFunction(a, b);
>

Of course "overuse" is always bad, by definition. :-)

But here the problem could also be the use of names such as foobar and
someFunction. Why do they not tell what is happening?!

When I see code like

auto iter = container.begin();

I know that auto means "some kind of iterator", and don't really care
about exactly which one it is.

And if it is

auto size = user_name.size();

it doesn't help a bit if auto is replaced by size_type, because what
type is size_type **really**?!

Perhaps if we see auto as an automatic typedef, we can hate it less?

Mut...@dastardlyhq.com

unread,
Dec 8, 2022, 10:48:24 AM12/8/22
to
On Thu, 8 Dec 2022 12:31:48 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Some C++ programmers do not use 'auto' merely to save some typing,
>as some kind of convenience feature. They go their way to use it
>pretty much everywhere they can, even when it doesn't actually save
>any typing or make anything more convenient. They use it like it were
>the generic variable declaration keyword in many other languages
>(quite typically "var").

To be fair you could use the same argument about templating. Many times
I've seem a template function thats only ever used for 2 different types.

Öö Tiib

unread,
Dec 8, 2022, 10:59:58 AM12/8/22
to
Yes but it is tedious. Some types are *LONG*, especially what templates
can return. Some are not possible to express. Like in functional
programming:

auto ret_fun() { return [](int x) { return x; }; }
auto& int_returner = ret_fun();

Should I wrap the return value into std::function<int(int)> to have it possible
to express its type? Is that free or brings some overhead? What if there
is combo of templates that accept as arguments and return lambdas?




Mr Flibble

unread,
Dec 8, 2022, 2:30:08 PM12/8/22
to
You should use a template if there are N types where N > 1, and guess
what? 2 > 1. Why? Because code duplication is bad even if there is only
one duplicate. You seem to be fractally wrong about most things.

/Flibble

Juha Nieminen

unread,
Dec 9, 2022, 7:52:59 AM12/9/22
to
Mut...@dastardlyhq.com wrote:
> To be fair you could use the same argument about templating. Many times
> I've seem a template function thats only ever used for 2 different types.

Incidentally, one of the things I have learned to hate when reading other
people's code (and which I could write an entire book about), is useless
function overloading that serves no purpose.

Way too often do you see code out there that overloads a function for
different types even though there's literally no technical reason nor
any sort of advantage in overloading it. It's done purely as a naming
thing, and that's it. There's no technical reason or purpose behind it.

You wouldn't believe, just like with the over-use of 'auto', how
frustratingly difficult it can be to read code that uses too much
function overloading at the expense of code readability and
understandability. That's because excessive overloading tends to
mean that the function name doesn't tell very explicitly what
it's doing, because the same name is being used for a myriad of
different types. Not only can this cause ambiguity from the
compiler's perspective, but it very much can cause ambiguity for the
person who is reading the code.

My personal opinion is: In the vast, vast majority of cases write
distinct function names for each distinct function (and the function
name should be quite clear about what it's doing, and how what
it's doing is different from the other functions that you would
have overloaded otherwise), and if you really, really need to
overload the function for some reason (eg. because the function is
being used in templated code), implement the overloads separately
and make them call the distinctively-named versions. And always use
the distinctively-named versions in your code unless there's an actual
good reason to use the overloaded versions. Readability is more important
than convenience.

Juha Nieminen

unread,
Dec 9, 2022, 7:56:48 AM12/9/22
to
Öö Tiib <oot...@hot.ee> wrote:
> Yes but it is tedious. Some types are *LONG*, especially what templates
> can return.

So what? I very much oppose the brevity-over-clarity style of programming.

What exactly are you saving by shortening names (especially if shortening
them to something that tells absolutely nothing about the actual type)?
Disk space? Or are you really in such a hurty that you can't spend a few
seconds typing the longer name?

> Some are not possible to express. Like in functional
> programming:

C++ lambdas are special in that the standard explicitly states that
they don't have a named type and that the only way to handle them is
with 'auto'.

In this case there's a good *technical* reason to use 'auto'. It's
not merely used for convenience or avoiding writing a couple of extra
characters.

Michael S

unread,
Dec 9, 2022, 8:03:47 AM12/9/22
to
You are maturing.
Few more years and you'll start to agree with your famous former compatriot.

"C++ is a horrible language. It's made more horrible by the fact that a lot
of substandard programmers use it, to the point where it's much much
easier to generate total and utter crap with it. Quite frankly, even if
the choice of C were to do *nothing* but keep the C++ programmers out,
that in itself would be a huge reason to use C.".

https://lwn.net/Articles/249460/

Scott Lurndal

unread,
Dec 9, 2022, 9:16:06 AM12/9/22
to
Sturgeon's Law applies.

Mut...@dastardlyhq.com

unread,
Dec 9, 2022, 10:52:29 AM12/9/22
to
As usual you're confusing your opinion with fact.

Öö Tiib

unread,
Dec 9, 2022, 10:57:47 AM12/9/22
to
On Friday, 9 December 2022 at 14:56:48 UTC+2, Juha Nieminen wrote:
> Öö Tiib <oot...@hot.ee> wrote:
> > Yes but it is tedious. Some types are *LONG*, especially what templates
> > can return.
> So what? I very much oppose the brevity-over-clarity style of programming.
>
> What exactly are you saving by shortening names (especially if shortening
> them to something that tells absolutely nothing about the actual type)?
> Disk space? Or are you really in such a hurty that you can't spend a few
> seconds typing the longer name?

I was not talking about "name" but "type" with number of template
arguments some of what are also templates and nested.The simpler
cases are almost tolerable but real types to deal with get hairy fast:
std::map<std::string_view, std::function<int(void)>>::insert_return_type
That when one should know fully well what map::insert returns
pair of its iterator and bool.

> > Some are not possible to express. Like in functional
> > programming:
> C++ lambdas are special in that the standard explicitly states that
> they don't have a named type and that the only way to handle them is
> with 'auto'.
>
> In this case there's a good *technical* reason to use 'auto'. It's
> not merely used for convenience or avoiding writing a couple of extra
> characters.

OK

Ben Bacarisse

unread,
Dec 9, 2022, 12:44:44 PM12/9/22
to
Juha Nieminen <nos...@thanks.invalid> writes:

> 嘱 Tiib <oot...@hot.ee> wrote:
>> Yes but it is tedious. Some types are *LONG*, especially what templates
>> can return.
>
> So what? I very much oppose the brevity-over-clarity style of
> programming.

As usual, such rules oversimplify the issues. Sometime clarity can
actually come from brevity.

It's usually more enlightening to give what you consider good and bad
examples as well some examples on the boundary. For example, I rarely
want to know more about the type when I see

for (const auto &elem : <something>) ...

Where in your spectrum of clarity vs. brevity does this sort of use come?

--
Ben.

Andreas Dehmel

unread,
Dec 9, 2022, 3:03:23 PM12/9/22
to
On Fri, 09 Dec 2022 17:44:27 +0000
Ben Bacarisse <ben.u...@bsb.me.uk> wrote:

> Juha Nieminen <nos...@thanks.invalid> writes:
I'd say it's on the lowest end of the spectrum. As soon as people start
decorating their "auto" with things like "const", "*" or "&" it
_always_ is. Either the type is self-explanatory or irrelevant, in
which case plain "auto" will do, or it isn't, in which case "auto" is
conceptually wrong. Decorating "auto" like that is just a pathetic
attempt at hiding this simple fact.


Andreas

Ben Bacarisse

unread,
Dec 9, 2022, 3:47:48 PM12/9/22
to
Andreas Dehmel <blackhole....@spamgourmet.com> writes:

> On Fri, 09 Dec 2022 17:44:27 +0000
> Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
>
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>> > 嘱 Tiib <oot...@hot.ee> wrote:
>> >> Yes but it is tedious. Some types are *LONG*, especially what
>> >> templates can return.
>> >
>> > So what? I very much oppose the brevity-over-clarity style of
>> > programming.
>>
>> As usual, such rules oversimplify the issues. Sometime clarity can
>> actually come from brevity.
>>
>> It's usually more enlightening to give what you consider good and bad
>> examples as well some examples on the boundary. For example, I rarely
>> want to know more about the type when I see
>>
>> for (const auto &elem : <something>) ...
>>
>> Where in your spectrum of clarity vs. brevity does this sort of use
>> come?
>
> I'd say it's on the lowest end of the spectrum. As soon as people start
> decorating their "auto" with things like "const", "*" or "&" it
> _always_ is. Either the type is self-explanatory or irrelevant, in
> which case plain "auto" will do, or it isn't, in which case "auto" is
> conceptually wrong. Decorating "auto" like that is just a pathetic
> attempt at hiding this simple fact.

If I read you correctly, you think that adding const means the auto is
almost always wrong. Is that your position?

--
Ben.

Tim Rentsch

unread,
Dec 9, 2022, 4:05:29 PM12/9/22
to
Juha Nieminen <nos...@thanks.invalid> writes:

> Tiib <oot...@hot.ee> wrote:
>
>> Yes but it is tedious. Some types are *LONG*, especially what templates
>> can return.
>
> So what? I very much oppose the brevity-over-clarity style of
> programming.

There is a tacit assumption in that statement that longer is
always easier to read or more readily comprehended. The
assumption is wrong. Good writers appreciate the difference
between lengthy phrasing and concise phrasing, using each as
appropriate, and varying wording choices between the two, to make
their writing more effective. That advice applies to programming
as much as it does to writing prose.

Tim Rentsch

unread,
Dec 9, 2022, 4:07:48 PM12/9/22
to
Andreas Dehmel <blackhole....@spamgourmet.com> writes:

> On Fri, 09 Dec 2022 17:44:27 +0000
> Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
>
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>>> [...] I very much oppose the brevity-over-clarity style of
>>> programming.
>>
>> As usual, such rules oversimplify the issues. Sometime clarity can
>> actually come from brevity.
>>
>> It's usually more enlightening to give what you consider good and
>> bad examples as well some examples on the boundary. For example, I
>> rarely want to know more about the type when I see
>>
>> for (const auto &elem : <something>) ...
>>
>> Where in your spectrum of clarity vs. brevity does this sort of use
>> come?
>
> I'd say it's on the lowest end of the spectrum. As soon as people start
> decorating their "auto" with things like "const", "*" or "&" it
> _always_ is. Either the type is self-explanatory or irrelevant, in
> which case plain "auto" will do, or it isn't, in which case "auto" is
> conceptually wrong. Decorating "auto" like that is just a pathetic
> attempt at hiding this simple fact.

The assertion that "auto" is conceptually wrong is an opinion,
not a fact.

Lynn McGuire

unread,
Dec 9, 2022, 4:26:06 PM12/9/22
to
Amen, brother ! Preach on !

Lynn

Andreas Dehmel

unread,
Dec 10, 2022, 8:51:36 AM12/10/22
to
On Fri, 09 Dec 2022 20:47:33 +0000
Like I wrote, my position is that adding _any_of_ "const", "*" or "&"
to auto is doing it wrong. It's just trying to hide the fact that you
actually want a specific type but are too lazy to write it down.

And as a general aside, not just relating to "auto", in a language like
C++ where you usually have a long maintenance window, the pains of the
author are insignificant compared to the pains of the maintainer(s).



Andreas

Christian Gollwitzer

unread,
Dec 10, 2022, 10:29:59 AM12/10/22
to
Am 08.12.22 um 13:31 schrieb Juha Nieminen:
> The problem in using 'auto' everywhere, from the perspective of someone
> who is reading the code, is that it hides the type in question. When
> you see something like:
>
> auto foobar = someFunction(a, b);
>
> it's a complete mystery what that return type is, and thus the reader
> (ie. me) has no idea what it actually is, what it does, and how it's
> used.

My question to you: why do you need to know the type of foobar in thie -
s case? Have you used dynamic languages like e.g. Python? THere the line
would read:

foobar = someFunction(a, b);

This has never be a big problem when writing Python code. "someFunction"
is a bad description of the return value, that is the problem here. You
wouldn't have the same difficulty to read:

auto x = concat("abc", "123");

or
auto d = sqrt(x**2 + y**2);


Christian

Ben Bacarisse

unread,
Dec 10, 2022, 4:53:07 PM12/10/22
to
That strikes me as a very strange opinion, but is there any point in us
(you and I) examining it? In my experience, investigating that sort of
opinion, expressed in that style, is rarely fruitful.

--
Ben.

Alf P. Steinbach

unread,
Dec 10, 2022, 6:29:45 PM12/10/22
to
Example.

class Holder
{
using Variant = variant<
// possible types here
>;

Variant m_variant;

public:
template< class Type >
Holder( in_<Type> e ): m_variant( e ) {}

template< class Type >
auto holds() const
-> bool
{
// TODO: optimize via compile time decisions (type lists).
const auto is_specified_type = []( const auto& e ) -> bool
{
return are_derived_and_base_< Unref_<decltype( e )>,
Type >;
};
return visit( is_specified_type, m_variant );
}


daniel...@gmail.com

unread,
Dec 10, 2022, 6:40:05 PM12/10/22
to
On Saturday, December 10, 2022 at 10:29:59 AM UTC-5, Christian Gollwitzer wrote:
> Am 08.12.22 um 13:31 schrieb Juha Nieminen:
> >
> > auto foobar = someFunction(a, b);
> >
> why do you need to know the type of foobar in thie -
> s case?

Minimally, you need to know whether someFunction returns a proxy, if it does,
you don't want to use auto. Functions returning proxies aren't that rare in
C++, matrix libraries such as Eigen use them extensively, and there's
even one in the standard library.
>
> This has never be a big problem when writing Python code

But Python is a more coherent language than C++.

Daniel

Andreas Dehmel

unread,
Dec 11, 2022, 8:37:42 AM12/11/22
to
Not sure whether you're arguing for or against, but
auto function(...) -> bool
can only be a bad joke and is_specified_type() is basically a bog
standard template function that thinks all the cool kids are using auto.



Andreas

David Brown

unread,
Dec 11, 2022, 10:43:15 AM12/11/22
to
When someone writes "const auto &elem", they are saying the details of
the actual type are not vital to the working of the code - but it /is/
important that the variable is "const" and a reference, giving efficient
read-only access.

It is emphasising and being explicit about the important aspects while
neatly omitting unimportant (for the code in question) details.


Chris M. Thomasson

unread,
Dec 11, 2022, 5:31:36 PM12/11/22
to
On 12/8/2022 4:31 AM, Juha Nieminen wrote:
> During the last few years I have had to read an inordinate amount of
> code written by other people. It has really given me a big insight on
> what makes code more and less readable and understandable. For example,
> I could write an entire book on naming conventions alone, and how they
> can make the code so much more readable, or make it almost inscrutable.
>
> But another thing I have really learned to hate is the overuse of the
> 'auto' keyword. I have always opposed its needless overuse, but this
> couple of years of reading other people's code has really confirmed
> and cemented my previous opinion on it.
>
> Some C++ programmers do not use 'auto' merely to save some typing,
> as some kind of convenience feature. They go their way to use it
> pretty much everywhere they can, even when it doesn't actually save
> any typing or make anything more convenient. They use it like it were
> the generic variable declaration keyword in many other languages
> (quite typically "var").
>
> The problem in using 'auto' everywhere, from the perspective of someone
> who is reading the code, is that it hides the type in question. When
> you see something like:
>
> auto foobar = someFunction(a, b)

[...]

Indeed. I find myself instantly looking for the declaration of
someFunction so I can make a note... foobar = a pointer to foobaz.

Juha Nieminen

unread,
Dec 12, 2022, 1:59:58 AM12/12/22
to
Michael S <already...@yahoo.com> wrote:
> You are maturing.
> Few more years and you'll start to agree with your famous former compatriot.
>
> "C++ is a horrible language. It's made more horrible by the fact that a lot
> of substandard programmers use it, to the point where it's much much
> easier to generate total and utter crap with it. Quite frankly, even if
> the choice of C were to do *nothing* but keep the C++ programmers out,
> that in itself would be a huge reason to use C.".
>
> https://lwn.net/Articles/249460/

I hope I never become that retarded.

Juha Nieminen

unread,
Dec 12, 2022, 2:04:42 AM12/12/22
to
Tim Rentsch <tr.1...@z991.linuxsc.com> wrote:
> Juha Nieminen <nos...@thanks.invalid> writes:
>
>> Tiib <oot...@hot.ee> wrote:
>>
>>> Yes but it is tedious. Some types are *LONG*, especially what templates
>>> can return.
>>
>> So what? I very much oppose the brevity-over-clarity style of
>> programming.
>
> There is a tacit assumption in that statement that longer is
> always easier to read or more readily comprehended.

No, there isn't. Overly short being hard to read does not mean that
overly long is easy to read. Overly long can perfectly well *also*
be hard to read.

You have to reach the optimal middle: Not too short, not too long.
The name must convey clearly its meaning. If you make it too
compressed or too sparse, it becomes harder to discern this meaning.

The problem I see in 99.99% of programming is that people tend to
always go with the overly short, usually for no reason whatsoever.

Juha Nieminen

unread,
Dec 12, 2022, 2:10:33 AM12/12/22
to
Christian Gollwitzer <auri...@gmx.de> wrote:
> Am 08.12.22 um 13:31 schrieb Juha Nieminen:
>> The problem in using 'auto' everywhere, from the perspective of someone
>> who is reading the code, is that it hides the type in question. When
>> you see something like:
>>
>> auto foobar = someFunction(a, b);
>>
>> it's a complete mystery what that return type is, and thus the reader
>> (ie. me) has no idea what it actually is, what it does, and how it's
>> used.
>
> My question to you: why do you need to know the type of foobar in thie -
> s case?

Because it helps me understand what that is doing, and what subsequent
lines are doing. There's quite a difference whehter that return type is
an int, a const char*, or a std::string, and if the return type is
specified right there, it immediately helps me understand what's
happening. The 'auto' tells me *absolutely nothing* about what's
happening there.

When 'auto' is used, the subsequent lines don't necessarily help me
know what that type is. Is it an 'int'? An 'unsigned int'? A 'double'?
A 'float'? Subsequent lines don't necessarily help me see which one
of those it is, or perhaps some other similar type. This information
is hidden from this piece of code, for no good reason.

> This has never be a big problem when writing Python code. "someFunction"
> is a bad description of the return value, that is the problem here. You
> wouldn't have the same difficulty to read:
>
> auto x = concat("abc", "123");

Does it return a const char*, or a std::string, or perhaps something else?
That's quite a big difference.

Juha Nieminen

unread,
Dec 12, 2022, 2:14:35 AM12/12/22
to
Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
> It's usually more enlightening to give what you consider good and bad
> examples as well some examples on the boundary. For example, I rarely
> want to know more about the type when I see
>
> for (const auto &elem : <something>) ...

I find it quite strange that you aren't interested in what that element
type is. When you know nothing about the type, you have no way of
knowing what to expect in the subsequent lines of code. Looking at
that line alone it may be completely unclear what it's actually doing
(depending on what that <something> is).

Compare it to, say:

for (const std::string& elem: <something>)

Aha! Now we know a lot more about what <something> is, and what to
expect in subsequent lines of code. Just that one little change is
giving us a lot more information and clarity about what's happening here.

David Brown

unread,
Dec 12, 2022, 2:55:06 AM12/12/22
to
On 12/12/2022 08:14, Juha Nieminen wrote:
> Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
>> It's usually more enlightening to give what you consider good and bad
>> examples as well some examples on the boundary. For example, I rarely
>> want to know more about the type when I see
>>
>> for (const auto &elem : <something>) ...
>
> I find it quite strange that you aren't interested in what that element
> type is. When you know nothing about the type, you have no way of
> knowing what to expect in the subsequent lines of code. Looking at
> that line alone it may be completely unclear what it's actually doing
> (depending on what that <something> is).
>

I find it strange that you expect to understand code line by line,
rather than looking at the context. This is especially true given that
full types in C++ can regularly take more than a single line to write out.

When I use "auto", it is because the details of the type don't matter
significantly, or they are clear from the context, or that they are too
convoluted to be convenient to write out manually, or that the code is
intended to be somewhat general. I think a combination of the first two
is the most common.

> Compare it to, say:
>
> for (const std::string& elem: <something>)
>
> Aha! Now we know a lot more about what <something> is, and what to
> expect in subsequent lines of code. Just that one little change is
> giving us a lot more information and clarity about what's happening here.

Compare it to :

void foo(std::vector<std::string> somethings) {

for (const auto &elem : somethings) ...

Why bother re-writing std::string inside the for loop? It doesn't make
the code any clearer or safer - it is unnecessary repetition.
(Programmers should have KISS tattooed on the inside of one eyelid, and
DRY tattooed on the inside of the other.) The types are clear as day.
And if they are changed - maybe "foo" gets changed to wide strings - the
rest of the code is unchanged with "auto". But if you have manually
written out the full type, you now have to remember to make changes in
more places or you've got highly unexpected conversions lying around.

/Overuse/ of auto is, of course, a bad thing - overuse of anything is
bad, by the definition of the word. And sometimes there are better
alternatives, such as "using" to make a local typename that is more
convenient, or concepts as "constrained auto". But very often, "auto"
is simple, convenient, improves clarity and reduces the risk of errors.
In such cases it is a very good thing.

Alf P. Steinbach

unread,
Dec 12, 2022, 3:35:50 AM12/12/22
to
It's good that you feel free to express your opinions in this group.

- Alf

David Brown

unread,
Dec 12, 2022, 3:49:40 AM12/12/22
to
I don't think anyone will disagree with you that manual typing is better
than "auto" when the exact type matters and it is not clear from the
context. But often the type details /don't/ matter, or they /are/ clear
from the context - and then "auto" is fine.

It's not really any different from all sorts of other aspects of
programming - you always have a balance between being explicit and
wordy, or being implicit and simpler.

Juha Nieminen

unread,
Dec 12, 2022, 6:32:13 AM12/12/22
to
David Brown <david...@hesbynett.no> wrote:
> I find it strange that you expect to understand code line by line,
> rather than looking at the context.

I don't find it strange at all. The clearer the code is, the better.
If you can understand what a line of code is doing without having
to look at the surrounding code, all the better. (Sometimes this is
just not possible, of course, but if with a simple change you can
make it so, why not?)

> This is especially true given that
> full types in C++ can regularly take more than a single line to write out.

There we go again with the brevity argument.

My disdain for overt brevity has not appeared out of the blue. It's the
consequence of years of having to have read tens of thousands of lines
of code written by other people.

Length does not matter. Clarity does.

> When I use "auto", it is because the details of the type don't matter
> significantly, or they are clear from the context, or that they are too
> convoluted to be convenient to write out manually, or that the code is
> intended to be somewhat general. I think a combination of the first two
> is the most common.

*Maybe* if what 'auto' expands to is *extremely* clear to see from the
code, then *perhaps* it's acceptable. However, my point is that 'auto'
is being *overused* a lot. In other words, in many situations where
it's *not* clear at all what it's expanding to (often requiring going
to an entirely different file to see what it actually is. IDEs help
with this, but IMO code should be readable without the help of any
IDEs.)

>> Compare it to, say:
>>
>> for (const std::string& elem: <something>)
>>
>> Aha! Now we know a lot more about what <something> is, and what to
>> expect in subsequent lines of code. Just that one little change is
>> giving us a lot more information and clarity about what's happening here.
>
> Compare it to :
>
> void foo(std::vector<std::string> somethings) {
>
> for (const auto &elem : somethings) ...

Then, in the future, as you further develop the code, you add a couple
dozen lines before that loop. Will you then change that 'auto' to the
actual type? Unlikely.

> Why bother re-writing std::string inside the for loop? It doesn't make
> the code any clearer or safer - it is unnecessary repetition.

It's not unnecessary repetition if it makes the code easier to understand.

You write the same words in your English prose again and again and again.
You don't see that as a problem. Why do you find it a problem in code?

> (Programmers should have KISS tattooed on the inside of one eyelid, and
> DRY tattooed on the inside of the other.)

No, because if you keep it stupid, then your code will be stupid, and
nobody will understand it.

Keep your code smart, not stupid.

> And if they are changed - maybe "foo" gets changed to wide strings - the
> rest of the code is unchanged with "auto". But if you have manually
> written out the full type, you now have to remember to make changes in
> more places or you've got highly unexpected conversions lying around.

Conversely, if you accidentally write the wrong type when refactoring
code, subsequent 'auto' keywords may hide your mistake, while explicit
types could have caught it immediately.

Juha Nieminen

unread,
Dec 12, 2022, 6:35:20 AM12/12/22
to
David Brown <david...@hesbynett.no> wrote:
> I don't think anyone will disagree with you that manual typing is better
> than "auto" when the exact type matters and it is not clear from the
> context. But often the type details /don't/ matter, or they /are/ clear
> from the context - and then "auto" is fine.

That sounds good in theory. In practice not so much.

As mentioned, I have learned the hate the over-use of 'auto' through the
process of having to read tends of thousands of lines of code written by
other people. Quite often even in situations where in theory "the type
doesn't matter", it makes reading the code more difficult precisely
because you don't know what type it is and why it "doesn't matter".
It makes the code harder to understand because you don't know what
it's dealing with.

Sometimes that's ok (such as in templated code). Sometimes it isn't.

David Brown

unread,
Dec 12, 2022, 10:11:55 AM12/12/22
to
On 12/12/2022 12:31, Juha Nieminen wrote:
> David Brown <david...@hesbynett.no> wrote:
>> I find it strange that you expect to understand code line by line,
>> rather than looking at the context.
>
> I don't find it strange at all. The clearer the code is, the better.
> If you can understand what a line of code is doing without having
> to look at the surrounding code, all the better. (Sometimes this is
> just not possible, of course, but if with a simple change you can
> make it so, why not?)
>

We agree that clearer code is better, all other things being equal. I
think that's a given. But we might disagree on what makes code clearer.

I gave several reasons why using an explicit type does not necessarily
make code "better", or why it might not be a "simple change". But even
when the change is simple, it would not necessarily bring any benefits.

To understand what code is doing, you almost always have to look at the
context. It is good that you should not have to look too far (or not
have to look far too often), but restricting your gaze to a single line
is arbitrarily and unnecessarily small.

>> This is especially true given that
>> full types in C++ can regularly take more than a single line to write out.
>
> There we go again with the brevity argument.

If you can't see the wood for the trees, the code is unhelpfully
long-winded.

Programming languages are based on the idea of shorter and more
convenient ways of referring to things - they are easier to read, easier
to write, easier to get correct, and more flexible. Why do we write
functions, rather than manually expanding them inline in your code?
Brevity makes the higher level function clearer. Why do we write "using
namespace" clauses, or "using" for type names? They make code clearer -
when used appropriately.

Making names too short or otherwise compacting code too much makes it
hard to read and comprehend. Making it all too long and verbose makes
it hard to read and comprehend. Pick a suitable middle ground.

>
> My disdain for overt brevity has not appeared out of the blue. It's the
> consequence of years of having to have read tens of thousands of lines
> of code written by other people.
>
> Length does not matter. Clarity does.

If you think clarity increases with length, you haven't read enough
code. Tens of thousands of lines is not a lot.

The sweet spot is /always/ in the middle.

Let's take a different case. If I want an integer to store numbers in
the range of 15 decimal digits, I'll write :

int64_t x;

I won't write :

signed long long int x;

even though the later is more portable, more explicit, and avoids an
unnecessary non-portable requirement of the implementation having a type
of exactly 64 bits. I won't even bother with "int_fast64_t", or
"int_least64_t". Technically, "signed long long int" is a more precise
specification for my needs. "int64_t" is much clearer, however - partly
because it is shorter.


A general rule of thumb is that for a given task, code in a higher level
language will take fewer lines than in a lower level language, and will
be clearer and contain fewer mistakes. (Studies show that the error
rate per line of code is mostly independent of the programming language
or the style of coding.) On the other hand, lower level languages give
you more control and often higher efficiency. C++ lets you do both high
and low level coding in the same language.

>
>> When I use "auto", it is because the details of the type don't matter
>> significantly, or they are clear from the context, or that they are too
>> convoluted to be convenient to write out manually, or that the code is
>> intended to be somewhat general. I think a combination of the first two
>> is the most common.
>
> *Maybe* if what 'auto' expands to is *extremely* clear to see from the
> code, then *perhaps* it's acceptable. However, my point is that 'auto'
> is being *overused* a lot. In other words, in many situations where
> it's *not* clear at all what it's expanding to (often requiring going
> to an entirely different file to see what it actually is. IDEs help
> with this, but IMO code should be readable without the help of any
> IDEs.)

I agree that IDE's help make code faster and easier to read (and
especially to navigate, if you need to move around) but should not be
necessary to understand code.

And no one disagrees with you that "auto" can be misused.


>
>>> Compare it to, say:
>>>
>>> for (const std::string& elem: <something>)
>>>
>>> Aha! Now we know a lot more about what <something> is, and what to
>>> expect in subsequent lines of code. Just that one little change is
>>> giving us a lot more information and clarity about what's happening here.
>>
>> Compare it to :
>>
>> void foo(std::vector<std::string> somethings) {
>>
>> for (const auto &elem : somethings) ...
>
> Then, in the future, as you further develop the code, you add a couple
> dozen lines before that loop. Will you then change that 'auto' to the
> actual type? Unlikely.
>

Will you need to change it to keep it clear? Unlikely.

If these dozen lines mean it is no longer clear, is changing "auto" to
an explicit type the best solution? /Very/ unlikely - in such a
situation, re-factoring the code (such as moving the dozen lines into
their own function) is going to give far greater benefits.


>> Why bother re-writing std::string inside the for loop? It doesn't make
>> the code any clearer or safer - it is unnecessary repetition.
>
> It's not unnecessary repetition if it makes the code easier to understand.
>

But in code like my snippet, it doesn't make it easier to understand.

> You write the same words in your English prose again and again and again.
> You don't see that as a problem. Why do you find it a problem in code?

Of course it can be a problem in prose. It can make the prose tedious
and therefore harder to read.

>
>> (Programmers should have KISS tattooed on the inside of one eyelid, and
>> DRY tattooed on the inside of the other.)
>
> No, because if you keep it stupid, then your code will be stupid, and
> nobody will understand it.
>
> Keep your code smart, not stupid.

KISS means "Keep it simple, stupid" - not "Keep it stupid". "auto" is
useful when it is simpler than manually and explicitly giving the type.

>
>> And if they are changed - maybe "foo" gets changed to wide strings - the
>> rest of the code is unchanged with "auto". But if you have manually
>> written out the full type, you now have to remember to make changes in
>> more places or you've got highly unexpected conversions lying around.
>
> Conversely, if you accidentally write the wrong type when refactoring
> code, subsequent 'auto' keywords may hide your mistake, while explicit
> types could have caught it immediately.

Write something once, and your chances of getting it wrong are lower
than writing it multiple types. Explicit types might just as easily
give you a conversion and hide your mistake.

Juha Nieminen

unread,
Dec 12, 2022, 10:59:29 AM12/12/22
to
David Brown <david...@hesbynett.no> wrote:
>>> This is especially true given that
>>> full types in C++ can regularly take more than a single line to write out.
>>
>> There we go again with the brevity argument.
>
> If you can't see the wood for the trees, the code is unhelpfully
> long-winded.

I don't think you understand.

The driving principle in writing code should be "this makes it easier to
understand", not "this makes it shorter".

It's not about making the names longer for the sake of making them longer.
It's about making them easier to understand. If that means writing longer
names, then so be it. There's zero reason to avoid longer names, if that
makes the code clearer for the reader who is reading the code for the
first time. (Conversely, if a name is so long that it makes it harder to
understand, then express it more concisely and clearly.)

The problem is that the majority of programmers do not choose names based
on how easy it makes the code to understand for third-parties. They choose
the names based on personal preference, which in the vast, vast majority
of cases means overtly short names. Most programmers prefer writing "ret"
instead of "returnValue", "err" instead of "errorCode", "genRandVal"
instead of "generateRandomValue". They do not think if that makes the
code harder for someone else to read. (And in the majority of cases if
you point this out, they will ferociously defend their practice, against
all logic.)

If 'std::map<std::string, std::string>' makes the code easier to understand
than 'auto', then write the former. There's no need to save disk space.
Shorter is not always better.

>> Length does not matter. Clarity does.
>
> If you think clarity increases with length, you haven't read enough
> code. Tens of thousands of lines is not a lot.

I have read enough code to know that brevity does not increase clarity,
but the opposite.

> Let's take a different case. If I want an integer to store numbers in
> the range of 15 decimal digits, I'll write :
>
> int64_t x;
>
> I won't write :
>
> signed long long int x;
>
> even though the later is more portable, more explicit, and avoids an
> unnecessary non-portable requirement of the implementation having a type
> of exactly 64 bits.

You are now trying to argue from redundancy. 'signed' and 'int' are
redundant there. They don't add information. There's no need to say the
same thing multiple times.

Also, those two lines are not equivalent. It's not *merely* about naming
conventions in this example. There's a functional difference.

>> Keep your code smart, not stupid.
>
> KISS means "Keep it simple, stupid" - not "Keep it stupid".

I suppose you choose to insult your readers then, rather than the second S
referring to the code itself.

Either way, I'd rather code be readable and understandable than simple.

Ben Bacarisse

unread,
Dec 12, 2022, 11:32:20 AM12/12/22
to
Juha Nieminen <nos...@thanks.invalid> writes:

> Ben Bacarisse <ben.u...@bsb.me.uk> wrote:
>> It's usually more enlightening to give what you consider good and bad
>> examples as well some examples on the boundary. For example, I rarely
>> want to know more about the type when I see
>>
>> for (const auto &elem : <something>) ...
>
> I find it quite strange that you aren't interested in what that element
> type is.

I think this captures the heart of the disagreement. In well-written
code, I would hope to not care. If the exact type of what this loop is
iterating over is crucial to understanding the loop or verifying that
the loop does what it should, then I would want to change the other
code, not the type in the loop.

But then I like to program (full disclosure: for fun only these days) in
Haskell which has, to all intents and purposes, a default auto. Types
are almost always inferred rather than stated.

> When you know nothing about the type, you have no way of
> knowing what to expect in the subsequent lines of code. Looking at
> that line alone it may be completely unclear what it's actually doing
> (depending on what that <something> is).
>
> Compare it to, say:
>
> for (const std::string& elem: <something>)
>
> Aha! Now we know a lot more about what <something> is, and what to
> expect in subsequent lines of code. Just that one little change is
> giving us a lot more information and clarity about what's happening
> here.

I would hope that knowing the type is not needed for verifying what the
loop is doing but I am aware that code is not always that well
organised.

--
Ben.

Scott Lurndal

unread,
Dec 12, 2022, 12:17:27 PM12/12/22
to
Juha Nieminen <nos...@thanks.invalid> writes:
>David Brown <david...@hesbynett.no> wrote:
>>>> This is especially true given that
>>>> full types in C++ can regularly take more than a single line to write out.
>>>
>>> There we go again with the brevity argument.
>>
>> If you can't see the wood for the trees, the code is unhelpfully
>> long-winded.
>
>I don't think you understand.
>
>The driving principle in writing code should be "this makes it easier to
>understand", not "this makes it shorter".

The two goals are not in conflict.

>The problem is that the majority of programmers do not choose names based

"Most"? got a cite?

>on how easy it makes the code to understand for third-parties. They choose
>the names based on personal preference, which in the vast, vast majority
>of cases means overtly short names. Most programmers prefer writing "ret"
>instead of "returnValue", "err" instead of "errorCode", "genRandVal"
>instead of "generateRandomValue".


"Most" programmers find uppercase characters in the
identifier are a productivity hit (more difficult
to type, for instance) and have no other redeeming
value.

I'll take 'rval' over "returnValue" every time.

long seed = random(); is perfectly readable and self documenting.

Michael S

unread,
Dec 12, 2022, 12:39:08 PM12/12/22
to
On Monday, December 12, 2022 at 5:11:55 PM UTC+2, David Brown wrote:
> On 12/12/2022 12:31, Juha Nieminen wrote:
> > You write the same words in your English prose again and again and again.
> > You don't see that as a problem. Why do you find it a problem in code?
>
> Of course it can be a problem in prose. It can make the prose tedious
> and therefore harder to read.

Marcus Tullius Cicero commonly considered a brilliant stylist, may be, GOAT.
I mean, by those who had read his writings, a group to which I don't belong.
Repetitions (periodic style) are one of his favorite tools.
However both Marcus Antonius and Marcus Aemilius Lepidus thought that
his style is tedious and convinced Octavian that Cicero has to be murdered.

Keith Thompson

unread,
Dec 12, 2022, 1:25:48 PM12/12/22
to
Juha Nieminen <nos...@thanks.invalid> writes:
> David Brown <david...@hesbynett.no> wrote:
>>>> This is especially true given that
>>>> full types in C++ can regularly take more than a single line to write out.
>>>
>>> There we go again with the brevity argument.
>>
>> If you can't see the wood for the trees, the code is unhelpfully
>> long-winded.
>
> I don't think you understand.
>
> The driving principle in writing code should be "this makes it easier to
> understand", not "this makes it shorter".

I think he *does* understand, but he disagrees.

It's easy to assume that someone can only disagree with you because they
don't understand what you're saying.

[...]

>>> Keep your code smart, not stupid.
>>
>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>
> I suppose you choose to insult your readers then, rather than the second S
> referring to the code itself.

The acronym "KISS" definitely expands to "Keep it simple, stupid", and
has since 1960. Nobody here chose what it means. Don't take it
personally.

https://en.wikipedia.org/wiki/KISS_principle

> Either way, I'd rather code be readable and understandable than simple.

If those goals conflict, I agree. They very often do not conflict.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for XCOM Labs
void Void(void) { Void(); } /* The recursive call of the void */

Ike Naar

unread,
Dec 12, 2022, 5:02:35 PM12/12/22
to
On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
> long seed = random(); is perfectly readable and self documenting.

The word choice is a bit unconventional.
A seed is most often used as an initial input to
a random number generator, not as the result of it.

Scott Lurndal

unread,
Dec 12, 2022, 5:42:12 PM12/12/22
to
It's common to seed a PRNG with a random number. Preferably
a true random number.

It wasn't uncommon in the early days of unix games to seed
the PRNG with the current time in seconds since the Epoch.

Keith Thompson

unread,
Dec 12, 2022, 7:00:21 PM12/12/22
to
sc...@slp53.sl.home (Scott Lurndal) writes:
> Ike Naar <i...@sdf.org> writes:
>>On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
>>> long seed = random(); is perfectly readable and self documenting.
>>
>>The word choice is a bit unconventional.
>>A seed is most often used as an initial input to
>>a random number generator, not as the result of it.
>
> It's common to seed a PRNG with a random number. Preferably
> a true random number.

If you can get a "true random number", you don't need a PRNG
(unless your source of true random numbers is slow or otherwise
resource-intensive). But it's rare to be able to get true random
numbers in the first place.

> It wasn't uncommon in the early days of unix games to seed
> the PRNG with the current time in seconds since the Epoch.

Which is hardly random.

Chris M. Thomasson

unread,
Dec 12, 2022, 7:04:39 PM12/12/22
to
On 12/8/2022 4:31 AM, Juha Nieminen wrote:
> During the last few years I have had to read an inordinate amount of
> code written by other people. It has really given me a big insight on
> what makes code more and less readable and understandable. For example,
> I could write an entire book on naming conventions alone, and how they
> can make the code so much more readable, or make it almost inscrutable.
>
> But another thing I have really learned to hate is the overuse of the
> 'auto' keyword. I have always opposed its needless overuse, but this
> couple of years of reading other people's code has really confirmed
> and cemented my previous opinion on it.
>
> Some C++ programmers do not use 'auto' merely to save some typing,
> as some kind of convenience feature. They go their way to use it
> pretty much everywhere they can, even when it doesn't actually save
> any typing or make anything more convenient. They use it like it were
> the generic variable declaration keyword in many other languages
> (quite typically "var").
>
> The problem in using 'auto' everywhere, from the perspective of someone
> who is reading the code, is that it hides the type in question. When
> you see something like:
>
> auto foobar = someFunction(a, b);
[...]

What about:

auto foobar = foobaz(a, b);
foobar->execute();


Well, what the hell does execute do?

struct missile_command
{
void execute() { // FIRE! }
};


Oh shit! foobaz returns a pointer to missle_command, well, shit happens.
Time to go into the bunker...

Ben Bacarisse

unread,
Dec 12, 2022, 7:34:00 PM12/12/22
to
"Chris M. Thomasson" <chris.m.t...@gmail.com> writes:

> On 12/8/2022 4:31 AM, Juha Nieminen wrote:
<cut>
>> The problem in using 'auto' everywhere, from the perspective of someone
>> who is reading the code, is that it hides the type in question. When
>> you see something like:
>> auto foobar = someFunction(a, b);
> [...]
>
> What about:
>
> auto foobar = foobaz(a, b);
> foobar->execute();
>
>
> Well, what the hell does execute do?
>
> struct missile_command
> {
> void execute() { // FIRE! }
> };
>
> Oh shit! foobaz returns a pointer to missle_command, well, shit
> happens. Time to go into the bunker...

These sorts of example are pure polemic since much of the problem in
comprehension comes from the names not the types.

auto missile = getLaunchAuthority(nominatedPerson1, nominatedPerson2);
missile->launch();

Clearer?

--
Ben.

Chris M. Thomasson

unread,
Dec 12, 2022, 8:14:10 PM12/12/22
to
On 12/12/2022 4:33 PM, Ben Bacarisse wrote:
> "Chris M. Thomasson" <chris.m.t...@gmail.com> writes:
>
>> On 12/8/2022 4:31 AM, Juha Nieminen wrote:
> <cut>
>>> The problem in using 'auto' everywhere, from the perspective of someone
>>> who is reading the code, is that it hides the type in question. When
>>> you see something like:
>>> auto foobar = someFunction(a, b);
>> [...]
>>
>> What about:
>>
>> auto foobar = foobaz(a, b);
>> foobar->execute();
>>
>>
>> Well, what the hell does execute do?
>>
>> struct missile_command
>> {
>> void execute() { // FIRE! }
>> };
>>
>> Oh shit! foobaz returns a pointer to missle_command, well, shit
>> happens. Time to go into the bunker...
>
> These sorts of example are pure polemic since much of the problem in
> comprehension comes from the names not the types.

Keep in mind that foobar could be a nullptr! Thank god.

Chris M. Thomasson

unread,
Dec 12, 2022, 8:25:20 PM12/12/22
to
On 12/12/2022 5:13 PM, Chris M. Thomasson wrote:
> On 12/12/2022 4:33 PM, Ben Bacarisse wrote:
>> "Chris M. Thomasson" <chris.m.t...@gmail.com> writes:
>>
>>> On 12/8/2022 4:31 AM, Juha Nieminen wrote:
>> <cut>
>>>> The problem in using 'auto' everywhere, from the perspective of someone
>>>> who is reading the code, is that it hides the type in question. When
>>>> you see something like:
>>>>       auto foobar = someFunction(a, b);
>>> [...]
>>>
>>> What about:
>>>
>>> auto foobar = foobaz(a, b);
>>> foobar->execute();
>>>
>>>
>>> Well, what the hell does execute do?
>>>
>>> struct missile_command
>>> {
>>>      void execute() { // FIRE! }
>>> };
>>>
>>> Oh shit! foobaz returns a pointer to missle_command, well, shit
>>> happens. Time to go into the bunker...

Ben keep in mind that missle_command is different than missile_command.

struct missle_command
{
void execute() { // Tell subs to launch. }
};

What auto is the right one?

Ben Bacarisse

unread,
Dec 12, 2022, 8:48:05 PM12/12/22
to
"Chris M. Thomasson" <chris.m.t...@gmail.com> writes:

> On 12/12/2022 5:13 PM, Chris M. Thomasson wrote:
>> On 12/12/2022 4:33 PM, Ben Bacarisse wrote:
>>> "Chris M. Thomasson" <chris.m.t...@gmail.com> writes:
>>>
>>>> On 12/8/2022 4:31 AM, Juha Nieminen wrote:
>>> <cut>
>>>>> The problem in using 'auto' everywhere, from the perspective of someone
>>>>> who is reading the code, is that it hides the type in question. When
>>>>> you see something like:
>>>>>       auto foobar = someFunction(a, b);
>>>> [...]
>>>>
>>>> What about:
>>>>
>>>> auto foobar = foobaz(a, b);
>>>> foobar->execute();
>>>>
>>>>
>>>> Well, what the hell does execute do?
>>>>
>>>> struct missile_command
>>>> {
>>>>      void execute() { // FIRE! }
>>>> };
>>>>
>>>> Oh shit! foobaz returns a pointer to missle_command, well, shit
>>>> happens. Time to go into the bunker...
>
> Ben keep in mind that missle_command is different than missile_command.
>
> struct missle_command
> {
> void execute() { // Tell subs to launch. }
> };
>
> What auto is the right one?

What has this got to do with the point I was making?

--
Ben.

Chris M. Thomasson

unread,
Dec 12, 2022, 8:49:05 PM12/12/22
to
In my very personal and humble opinion, auto has the ability to send a
chill up my spine...

Chris M. Thomasson

unread,
Dec 12, 2022, 10:48:11 PM12/12/22
to
On 12/12/2022 5:13 PM, Chris M. Thomasson wrote:
Ahh, you meant getLaunchAuthoritySub right?


Chris M. Thomasson

unread,
Dec 12, 2022, 10:51:17 PM12/12/22
to
getLaunchAuthority for what?

getLaunchAuthority_Anti_Satellite

Or,

auto auth = create_launch_authority_sam_sites(nominatedPerson1,
nominatedPerson2);

if (auth)
{
launch(auth);
}


Chris M. Thomasson

unread,
Dec 12, 2022, 10:53:57 PM12/12/22
to
lanuch(auth) vs launch_at_will_commander(auth).

Chris M. Thomasson

unread,
Dec 12, 2022, 11:09:13 PM12/12/22
to
On 12/12/2022 4:33 PM, Ben Bacarisse wrote:
You still forgot to check for nullptr:

if (missile) missile->launch();

James Kuyper

unread,
Dec 13, 2022, 2:48:49 AM12/13/22
to
On 12/12/22 19:00, Keith Thompson wrote:
> sc...@slp53.sl.home (Scott Lurndal) writes:
...
>> It's common to seed a PRNG with a random number. Preferably
>> a true random number.
>
> If you can get a "true random number", you don't need a PRNG
> (unless your source of true random numbers is slow or otherwise
> resource-intensive).

It's my understanding that there are indeed hardware sources of truly
random numbers based upon some physically random phenomenon such as
thermal noise. They are in fact very slow, and as a result are often
used to seed much faster pseudo-random number generators.

Chris M. Thomasson

unread,
Dec 13, 2022, 3:03:36 AM12/13/22
to
On 12/12/2022 4:00 PM, Keith Thompson wrote:
> sc...@slp53.sl.home (Scott Lurndal) writes:
>> Ike Naar <i...@sdf.org> writes:
>>> On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
>>>> long seed = random(); is perfectly readable and self documenting.
>>>
>>> The word choice is a bit unconventional.
>>> A seed is most often used as an initial input to
>>> a random number generator, not as the result of it.
>>
>> It's common to seed a PRNG with a random number. Preferably
>> a true random number.
>
> If you can get a "true random number", you don't need a PRNG
> (unless your source of true random numbers is slow or otherwise
> resource-intensive). But it's rare to be able to get true random
> numbers in the first place.
>
>> It wasn't uncommon in the early days of unix games to seed
>> the PRNG with the current time in seconds since the Epoch.
>
> Which is hardly random.
>

Shake a big box containing a shit load of 16 sided dice up really
good... Unplug a hole and shake it until a single die drops out. Hey, we
just got a nibble! ;^)

Shake and repeat. lol.

Juha Nieminen

unread,
Dec 13, 2022, 3:24:51 AM12/13/22
to
Scott Lurndal <sc...@slp53.sl.home> wrote:
> "Most" programmers find uppercase characters in the
> identifier are a productivity hit (more difficult
> to type, for instance) and have no other redeeming
> value.

If you want to use camelCase or snake_case that's just fine, as long
as it's consistent and readable. That's not the point.

> I'll take 'rval' over "returnValue" every time.

Exactly my point. Thanks for demonstrating.

> long seed = random(); is perfectly readable and self documenting.

At least it's using full English words, which is a step in the right
direction.

Juha Nieminen

unread,
Dec 13, 2022, 3:33:08 AM12/13/22
to
Keith Thompson <Keith.S.T...@gmail.com> wrote:
> Juha Nieminen <nos...@thanks.invalid> writes:
>> David Brown <david...@hesbynett.no> wrote:
>>>>> This is especially true given that
>>>>> full types in C++ can regularly take more than a single line to write out.
>>>>
>>>> There we go again with the brevity argument.
>>>
>>> If you can't see the wood for the trees, the code is unhelpfully
>>> long-winded.
>>
>> I don't think you understand.
>>
>> The driving principle in writing code should be "this makes it easier to
>> understand", not "this makes it shorter".
>
> I think he *does* understand, but he disagrees.
>
> It's easy to assume that someone can only disagree with you because they
> don't understand what you're saying.

I didn't actually meant that he didn't understand what I was saying.
My choice of words was poor. I meant it more like "you are missing the
point".

>>>> Keep your code smart, not stupid.
>>>
>>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>>
>> I suppose you choose to insult your readers then, rather than the second S
>> referring to the code itself.
>
> The acronym "KISS" definitely expands to "Keep it simple, stupid", and
> has since 1960. Nobody here chose what it means.

I know perfectly well what it expands to, and I still maintain that if you
deliberately want to interpret it as the "stupid" referring to the person
that the sentiment is directed to, it's insulting. I don't care if that's
exactly what it originally meant. If it was originally insulting, then it's
still insulting. I don't even understand what the person who came up with
it was thinking. No wonder there are myriads of alternatives that replace
the "stupid" with something less offensive.

I kind of give the benefit of the doubt to the original author of the
acronym and prefer to interpret it as it referring to keeping the thing
"simple and stupid", rather than keeping the thing "simple" and calling
the person "stupid". (If this is the interpretation, then "keeping the
thing stupid" would mean something like "don't try to make it too clever
for its own good". After all "stupid" and "simple" can be thought of
as synonyms.)

>> Either way, I'd rather code be readable and understandable than simple.
>
> If those goals conflict, I agree. They very often do not conflict.

When "simple" is interpreted as "short" (eg. using just one word
instead of three) then quite often they are in conflict, especially
when speaking about code.

David Brown

unread,
Dec 13, 2022, 3:42:32 AM12/13/22
to
On 12/12/2022 16:59, Juha Nieminen wrote:
> David Brown <david...@hesbynett.no> wrote:
>>>> This is especially true given that
>>>> full types in C++ can regularly take more than a single line to write out.
>>>
>>> There we go again with the brevity argument.
>>
>> If you can't see the wood for the trees, the code is unhelpfully
>> long-winded.
>
> I don't think you understand.
>
> The driving principle in writing code should be "this makes it easier to
> understand", not "this makes it shorter".
>

Of course I understand, and agree with that principle. The sticking
point seems to be that you apparently have difficulty understanding that
short code can be easy to understand - easier than long versions.
Sometimes it is simply the fact that the code is shorter that makes it
easier to understand - people generally write "long" instead of "signed
long int" precisely because it is shorter and requires less cognitive
effort to understand.

"auto", used appropriately, can do the same thing.


> It's not about making the names longer for the sake of making them longer.
> It's about making them easier to understand. If that means writing longer
> names, then so be it. There's zero reason to avoid longer names, if that
> makes the code clearer for the reader who is reading the code for the
> first time. (Conversely, if a name is so long that it makes it harder to
> understand, then express it more concisely and clearly.)
>
> The problem is that the majority of programmers do not choose names based
> on how easy it makes the code to understand for third-parties. They choose
> the names based on personal preference, which in the vast, vast majority
> of cases means overtly short names. Most programmers prefer writing "ret"
> instead of "returnValue", "err" instead of "errorCode", "genRandVal"
> instead of "generateRandomValue". They do not think if that makes the
> code harder for someone else to read. (And in the majority of cases if
> you point this out, they will ferociously defend their practice, against
> all logic.)

Of course they write "ret" instead of "returnValue" - it makes the code
easier to understand!

Choosing and using good names is an art. There are guidelines, but no
fixed rules. Like many stylistic aspects of programming, it can depend
significantly on the size of the project, the size of the development
group, the lifetime of the code, the type of code, and many other factors.

One common rule, however, is that the bigger the scope of an identifier,
the longer and more explicit it must be. Inside a short loop, you use
an index variable "i" because it is short and /clear/. Calling it
"loop_index_counter" makes the code harder to read and understand -
longer and more explicit is directly counter-productive. A function
that could be called from anywhere in a million-line program, on the
other hand, needs a very good and clear name - though that is almost
certainly best done via appropriate uses of namespaces (or other
structured naming) rather than a long identifier. (C++ is not C.)

Compare:

int calculate_average_of_vector_of_ints(std::vector<int>
vector_of_ints_to_average)
{
int sum_so_far = 0;
for (this_int : vector_of_ints_to_average) {
sum_so_far += this_int;
}
int the_size_of_the_vector_of_ints_to_average =
vector_of_ints_to_average.size();
int return_value = sum_so_far /
the_size_of_the_vector_of_ints_to_average;
return return_value;
}

with :

int average(std::vector<int> xs) {
{
int sum = 0;
for (x : xs) {
sum += x;
}
return sum / xs.size();
}


Are you seriously suggesting that the first version is "clearer" or
easier to understand, because it has long, explicit names?


If I see someone use a variable called "returnValue" in something
presented for code review, I'd reject it. It's a name that means
nothing (what information does it give you in "return returnValue;" ?)
The only conceivable reason to have it is that the function is so long
the it is unclear what it is returning - and /that/ is the problem to fix.

The same goes for "errorCode". If it is not clear from the code that
"err" is an error code, /that/ is the problem - not the name of the
variable.

If we are talking about functions accessible from far off in the code,
then longer names are needed. But not local names.


>
> If 'std::map<std::string, std::string>' makes the code easier to understand
> than 'auto', then write the former. There's no need to save disk space.
> Shorter is not always better.

I fully agree - no one has argued any differently.

What people (generalising wildly from myself) are reacting against is
your idea that shorter /cannot/ be better, or that longer is /always/
better.

When used correctly, shorter most certainly can be better precisely
because it is clearer and easier to understand - and it is clearer and
easier to understand precisely because it is better.

That only applies when it is clear what the identifier means, of course.
And that will vary enormously according to the rest of the code.


>
>>> Length does not matter. Clarity does.
>>
>> If you think clarity increases with length, you haven't read enough
>> code. Tens of thousands of lines is not a lot.
>
> I have read enough code to know that brevity does not increase clarity,
> but the opposite.
>
>> Let's take a different case. If I want an integer to store numbers in
>> the range of 15 decimal digits, I'll write :
>>
>> int64_t x;
>>
>> I won't write :
>>
>> signed long long int x;
>>
>> even though the later is more portable, more explicit, and avoids an
>> unnecessary non-portable requirement of the implementation having a type
>> of exactly 64 bits.
>
> You are now trying to argue from redundancy. 'signed' and 'int' are
> redundant there. They don't add information. There's no need to say the
> same thing multiple times.

You are being inconsistent. Writing "signed" makes it clear and
explicit that we are dealing with signed types - no one has to read
"int" or "int64_t" and remember that by default integers are signed in
C++. Or are you happy that /sometimes/ it's okay to write short code
whose meaning is clear to everyone reading it, and you don't have to
write out /everything/ in the longest, most explicit manner?

I think it turns out that you too understand that "a happy medium" is
the ideal - not too long, not too short, not too explicit, not too
implicit. You might have a personal preference towards slightly longer
than the preferences of the "average" programmer, but that's detail
rather than principle.


>
> Also, those two lines are not equivalent. It's not *merely* about naming
> conventions in this example. There's a functional difference.
>

There is - and I know the difference, and stated it. But I actively
choose the version that is marginally subpar in the technicalities of
what the code means, precisely because the "int64_t" version is clearer
and easier to understand, primarily because it is shorter.

>>> Keep your code smart, not stupid.
>>
>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>
> I suppose you choose to insult your readers then, rather than the second S
> referring to the code itself.
>

"KISS" is a well-known acronym and guiding principle throughout
engineering (not just programming). The "stupid" is not an insult as
such, and is targeted at the developer not the reader - it means it is a
stupid idea to make things more complicated than necessary.

If you prefer Einstein's version, "make things as simple as possible,
but no simpler".

> Either way, I'd rather code be readable and understandable than simple.

I'd rather it be /both/ - because they are strongly correlated. Simple
code is easier to read and understand.

Keith Thompson

unread,
Dec 13, 2022, 4:12:06 AM12/13/22
to
Juha Nieminen <nos...@thanks.invalid> writes:
> Keith Thompson <Keith.S.T...@gmail.com> wrote:
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>> David Brown <david...@hesbynett.no> wrote:
>>>>>> This is especially true given that
>>>>>> full types in C++ can regularly take more than a single line to write out.
>>>>>
>>>>> There we go again with the brevity argument.
>>>>
>>>> If you can't see the wood for the trees, the code is unhelpfully
>>>> long-winded.
>>>
>>> I don't think you understand.
>>>
>>> The driving principle in writing code should be "this makes it easier to
>>> understand", not "this makes it shorter".
>>
>> I think he *does* understand, but he disagrees.
>>
>> It's easy to assume that someone can only disagree with you because they
>> don't understand what you're saying.
>
> I didn't actually meant that he didn't understand what I was saying.
> My choice of words was poor. I meant it more like "you are missing the
> point".

I doubt that he his, but I'll refrain from further attempts to speak for him.

>>>>> Keep your code smart, not stupid.
>>>>
>>>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>>>
>>> I suppose you choose to insult your readers then, rather than the second S
>>> referring to the code itself.
>>
>> The acronym "KISS" definitely expands to "Keep it simple, stupid", and
>> has since 1960. Nobody here chose what it means.
>
> I know perfectly well what it expands to, and I still maintain that if you
> deliberately want to interpret it as the "stupid" referring to the person
> that the sentiment is directed to, it's insulting. I don't care if that's
> exactly what it originally meant. If it was originally insulting, then it's
> still insulting. I don't even understand what the person who came up with
> it was thinking. No wonder there are myriads of alternatives that replace
> the "stupid" with something less offensive.

That's a valid opinion, but plenty of people use the term, knowing
exactly what it means, without meaning to be insulting. It's
humor, which can be a very individual thing. I understand that you find
it offensive. Please understand that others find it more humorous than
offensive, even understanding what it means.

If someone directly calls me stupid, I'll be insulted. But as part of a
well known saying that's been around for decades, it's different in ways
I'm not sure I can explain. And I'm at least as likely to apply it to
myself as to others.

See also RTFM.

> I kind of give the benefit of the doubt to the original author of the
> acronym and prefer to interpret it as it referring to keeping the thing
> "simple and stupid", rather than keeping the thing "simple" and calling
> the person "stupid". (If this is the interpretation, then "keeping the
> thing stupid" would mean something like "don't try to make it too clever
> for its own good". After all "stupid" and "simple" can be thought of
> as synonyms.)

It's not at all plausible that Kelly Johnson, cited as the originator of
the term, meant "simple and stupid". It's 100% clear that the word
"simple" refers to the thing and "stupid" refers to the person being
spoken to (implying that they're stupid for not designing the thing to
be simple). Again, I understand if you find that insulting, but it's a
form of humor that a lot of us find amusing and inoffensive.

>>> Either way, I'd rather code be readable and understandable than simple.
>>
>> If those goals conflict, I agree. They very often do not conflict.
>
> When "simple" is interpreted as "short" (eg. using just one word
> instead of three) then quite often they are in conflict, especially
> when speaking about code.

I don't think anyone is arguing that brevity is the only thing that
contributes to simplicity.

Juha Nieminen

unread,
Dec 13, 2022, 5:20:18 AM12/13/22
to
David Brown <david...@hesbynett.no> wrote:
> Of course I understand, and agree with that principle. The sticking
> point seems to be that you apparently have difficulty understanding that
> short code can be easy to understand - easier than long versions.

Believe me, by this point in my life I have read enough other people's
code to know for a fact that overtly short naming schemes make code harder
to understand, not easier.

You can claim the opposite until the cows come home, but you cannot erase
my personal experience of *actually* having read *tons and tons* of code
written by other people, and seeing the difference it makes when things
are clearly named vs. when cryptic abbreviations and acronyms are used,
or when too few words are used to describe the variable, function or type,
or when eg. types are being hidden behind 'auto' keywords for no good
reason. (Also, when function overloading is overused for no good reason.)

> Sometimes it is simply the fact that the code is shorter that makes it
> easier to understand - people generally write "long" instead of "signed
> long int" precisely because it is shorter and requires less cognitive
> effort to understand.

There's absolutely nothing in "signed long int" that makes it harder to
understand than "long". It just has a lot of redundancy that doesn't add
any relevant information.

But compare that to, for example let's say, a function named "generate()".
Generate what, exactly? That function name would benefit a great deal from
additional words that describe what it's generating (and this information
would not be redundant). Or consider a function named "convert()". Convert
what, exactly? And into what? This, too, would greatly benefit from having
more words telling the reader what it's doing.

This is different from "signed long" vs "long", where the additional word
doesn't add any new clarifying information and is redundant. But by all
means, if you want to specify the 'signed' for extra clarity, go right
ahead. It doesn't make it harder to understand.

> "auto", used appropriately, can do the same thing.

I can't think of many situations where 'auto' actually increases how
easy the code is to understand. There might be situations where it doesn't
decrease understandability, but not many situations where it actually
increases it.

> Of course they write "ret" instead of "returnValue" - it makes the code
> easier to understand!

It absolutely doesn't. It only makes code more compressed and removes
useful information. At the very most you could perhaps claim that it
doesn't make the code harder to understand. It absoutely does not make
the code *easier* to understand.

> One common rule, however, is that the bigger the scope of an identifier,
> the longer and more explicit it must be. Inside a short loop, you use
> an index variable "i" because it is short and /clear/. Calling it
> "loop_index_counter" makes the code harder to read and understand -
> longer and more explicit is directly counter-productive.

It being longer doesn't make it harder to understand. In this particular
example you are just, once again, adding *redundant* information to it.

"index" is better than both "i" (because "index" is an actual English
word that expresses what the variable is) and "loop_index_counter"
(because it contains useless redundant information).

A better name than "index" would be to express what it's indexing.
For example "coordinate_index", or "word_index", or "column_index",
or whatever it's indexing is better than just "index" because it's
actually telling you what it's used for.

For the millionth time: It's not about making the names *longer*.
It's about making the *clearer*. There's a difference.

Do you understand what I'm trying to say?

Juha Nieminen

unread,
Dec 13, 2022, 6:13:53 AM12/13/22
to
Juha Nieminen <nos...@thanks.invalid> wrote:
> Believe me, by this point in my life I have read enough other people's
> code to know for a fact that overtly short naming schemes make code harder
> to understand, not easier.

Not that probably anybody is interested, but anyway, after all that I have
come up with a few principles when it comes to naming in order to make
code easier for a third-party (who has never seen the code before) to read:

- Always use full English words instead of contractions and acronyms.
"return_value" is better than "ret". "error_code" is better than "err".
"generateRandomValue" is better than "genRandVal". "column_index" is
better than "i".
(An exception is if the contraction or acronym is universally used and
understood, like "GPS", "HDMI", "cos", "tan", etc.)

- Use as many words as needed to make it clear what the variable, function
or type is doing (but in general avoid redundancy, as that doesn't really
add any useful information to the name).
"error_code" is better than "error" or "code". "convert_to_utf16_from_utf8"
is better than "convert".
(Note: It's not about making the name longer. It's about making it clearer
and more unambiguous, and easier to understand what it's doing.)

- Don't use function overloading unless there's an actual good reason
to use it (eg. because the function will be used in templated code).
Avoid overloading just for the sake of overloading. Always name the
functions in a disambiguating descriptive manner and prefer unique names,
if possible. (Even when overloading is needed, prefer still implementing
the functions with unique names, and make the overloads call those. In
code that doesn't need the overloading call the uniquely named versions
of the functions.)

- Don't overuse 'auto'. Use it only when there's a good technical
reason to use it. Don't use it to merely save typing, or as some kind
of equivalent to a 'var' keyword in other languages.
If there's a type that's extremely long when typed out in its entirety,
you could create a 'using' alias that's shorter but still as clear and
unambiguous as possible (that still makes it very clear what it is).

- Almost always use namespace prefixes when using names inside a
namespace, even in code that's inside the same namespace. (This is
because when the namespace appears in the name, it makes it very
clear that the name is from that namespace and not a function-local
name, a class member, or a global name somewhere else.)

Ben Bacarisse

unread,
Dec 13, 2022, 6:39:13 AM12/13/22
to
So did you. I left that unaddressed because it has nothing to do with
my point. Once again, examples like yours (with or without the nullptr
side issues) don't help because, very often, the confusion comes from
the neutral and unhelpful names rather than the language feature (in
that case auto) that is being discussed.

--
Ben.

Paavo Helde

unread,
Dec 13, 2022, 7:39:35 AM12/13/22
to
13.12.2022 02:00 Keith Thompson kirjutas:
> sc...@slp53.sl.home (Scott Lurndal) writes:
>> Ike Naar <i...@sdf.org> writes:
>>> On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
>>>> long seed = random(); is perfectly readable and self documenting.
>>>
>>> The word choice is a bit unconventional.
>>> A seed is most often used as an initial input to
>>> a random number generator, not as the result of it.
>>
>> It's common to seed a PRNG with a random number. Preferably
>> a true random number.
>
> If you can get a "true random number", you don't need a PRNG
> (unless your source of true random numbers is slow or otherwise
> resource-intensive).

In Linux there are /dev/random and /dev/urandom. The first one ought to
be slower and more random (gathers "environmental noise from device
drivers") than the other, although /dev/urandom is nowadays supposed to
be also good for almost anything, including cryptographic purposes.

I once had to fix a bug where my program stalled. It appeared I had
thoughtlessly used /dev/random for filling some random pool, and as the
program was run in a stripped-down Linux VM without any direct
connection to physical hardware, the system ran out of random data for
/dev/random and the program hanged indefinitely when trying to read it.


David Brown

unread,
Dec 13, 2022, 8:11:13 AM12/13/22
to
On 13/12/2022 01:00, Keith Thompson wrote:
> sc...@slp53.sl.home (Scott Lurndal) writes:
>> Ike Naar <i...@sdf.org> writes:
>>> On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
>>>> long seed = random(); is perfectly readable and self documenting.
>>>
>>> The word choice is a bit unconventional.
>>> A seed is most often used as an initial input to
>>> a random number generator, not as the result of it.
>>
>> It's common to seed a PRNG with a random number. Preferably
>> a true random number.
>
> If you can get a "true random number", you don't need a PRNG
> (unless your source of true random numbers is slow or otherwise
> resource-intensive). But it's rare to be able to get true random
> numbers in the first place.

True random data - or at least high entropy data - is almost always
slow. It also often has an awkward distribution (such as Binomial or
Poisson, rather than convenient linear distribution). So the standard
practice is to use the high entropy data to seed a pseudo-random number
generator from your high entropy source.

>
>> It wasn't uncommon in the early days of unix games to seed
>> the PRNG with the current time in seconds since the Epoch.
>
> Which is hardly random.
>

It makes no sense to call a seed "random" or not. It can be
non-deterministic (and the current time in seconds is non-deterministic
enough for a great many purposes - certainly for games). But only a
distribution can be random, not a single number.

Higher quality seeds with greater entropy combine multiple sources, such
as the least-significant bit of temperature measurements, microsecond
times between network packets or keyboard clicks, etc. (You have to be
careful how you combine them - simply adding them is not a good idea!)

David Brown

unread,
Dec 13, 2022, 8:31:30 AM12/13/22
to
On 13/12/2022 10:11, Keith Thompson wrote:
> Juha Nieminen <nos...@thanks.invalid> writes:
>> Keith Thompson <Keith.S.T...@gmail.com> wrote:
>>> Juha Nieminen <nos...@thanks.invalid> writes:
>>>> David Brown <david...@hesbynett.no> wrote:
>>>>>>> This is especially true given that
>>>>>>> full types in C++ can regularly take more than a single line to write out.
>>>>>>
>>>>>> There we go again with the brevity argument.
>>>>>
>>>>> If you can't see the wood for the trees, the code is unhelpfully
>>>>> long-winded.
>>>>
>>>> I don't think you understand.
>>>>
>>>> The driving principle in writing code should be "this makes it easier to
>>>> understand", not "this makes it shorter".
>>>
>>> I think he *does* understand, but he disagrees.
>>>
>>> It's easy to assume that someone can only disagree with you because they
>>> don't understand what you're saying.
>>
>> I didn't actually meant that he didn't understand what I was saying.
>> My choice of words was poor. I meant it more like "you are missing the
>> point".
>
> I doubt that he his, but I'll refrain from further attempts to speak for him.

You are doing fine so far :-)

Yes, I understand Juha's point, but I disagree with it. At least, I
disagree with the level or strength of it.

Clear code is vitally important in all but throw-away code. (Remember
Heathfield's rule? It's easier to make clear code correct than to make
correct code clear. It's easier to make correct code fast than to make
fast code correct. So always code for clarity.)

And awkward or exaggerated abbreviations make code unclear. They may
seem fine at the time to the person writing the code, but it's a
different matter a decade later for someone else maintaining it.

So I think there is a scale here of some kind, from short, concise or
abbreviated at one end and long-winded, explicit and expanded at the
other end. I think (unjustifiably speaking for everyone here!) we all
agree that being too close to the short end is a bad idea. The
disagreement is towards the other end - I say that's bad too, while
Juha, AFAICS, disagrees.


>
>>>>>> Keep your code smart, not stupid.
>>>>>
>>>>> KISS means "Keep it simple, stupid" - not "Keep it stupid".
>>>>
>>>> I suppose you choose to insult your readers then, rather than the second S
>>>> referring to the code itself.
>>>
>>> The acronym "KISS" definitely expands to "Keep it simple, stupid", and
>>> has since 1960. Nobody here chose what it means.
>>
>> I know perfectly well what it expands to, and I still maintain that if you
>> deliberately want to interpret it as the "stupid" referring to the person
>> that the sentiment is directed to, it's insulting. I don't care if that's
>> exactly what it originally meant. If it was originally insulting, then it's
>> still insulting. I don't even understand what the person who came up with
>> it was thinking. No wonder there are myriads of alternatives that replace
>> the "stupid" with something less offensive.
>
> That's a valid opinion, but plenty of people use the term, knowing
> exactly what it means, without meaning to be insulting. It's
> humor, which can be a very individual thing. I understand that you find
> it offensive. Please understand that others find it more humorous than
> offensive, even understanding what it means.
>
> If someone directly calls me stupid, I'll be insulted. But as part of a
> well known saying that's been around for decades, it's different in ways
> I'm not sure I can explain. And I'm at least as likely to apply it to
> myself as to others.
>
> See also RTFM.

If someone is directly called "stupid", it is insulting. However, it's
a different matter if someone says "you're being stupid", or "that code
you wrote is stupid", or "you said something stupid". I do not consider
myself a stupid person - but like most people, I sometimes do stupid
things or say something stupid.

If someone gives me a piece of code to review and I return it with
"KISS" scrawled across it in big red pen, I am /not/ calling the
developer stupid - nor insulting them. I am telling them that I think
the code has got out of hand and ended up being too complex - and that
they could do a better job if they simplified it. (I haven't done this
with a code review, but I did do it once with an electronics design
review. The designer was not insulted, and agreed with my point.)


Juha Nieminen

unread,
Dec 13, 2022, 8:42:22 AM12/13/22
to
David Brown <david...@hesbynett.no> wrote:
> So I think there is a scale here of some kind, from short, concise or
> abbreviated at one end and long-winded, explicit and expanded at the
> other end. I think (unjustifiably speaking for everyone here!) we all
> agree that being too close to the short end is a bad idea. The
> disagreement is towards the other end - I say that's bad too, while
> Juha, AFAICS, disagrees.

I don't really understand why this seems to be so hard to explain.

I don't want names that are long. I want names that are clear, unambiguous
and easy to understand, which convey as well as possible what the name
is representing.

Overtly short abbreviated names do not convey that, and code that's too
compressed and contains too much information packed in too little space
does not achieve that.

The goal is not to make names or code longer. That's just a side-effect
of making code clearer and easier to understand. And yes, it is perfectly
possible to go too far in the other direction. But that has nothing to
do with what I'm saying. I want clarity, not length. Clarity sometimes
requires increasing length a bit, but that in itself is irrelevant, it's
just a side effect.

Thus I find it ridiculous when people post "counter-examples" that are
names that are overly long and contain a lot of rendunancy. I'm not
looking for long names. I'm looking for clear names. There's a
difference.

How hard is this to understand, really?

daniel...@gmail.com

unread,
Dec 13, 2022, 9:44:05 AM12/13/22
to
On Tuesday, December 13, 2022 at 3:42:32 AM UTC-5, David Brown wrote:
> >
> short code can be easy to understand - easier than long versions.
> Sometimes it is simply the fact that the code is shorter that makes it
> easier to understand - people generally write "long" instead of "signed
> long int" precisely because it is shorter and requires less cognitive
> effort to understand.
>
> "auto", used appropriately, can do the same thing.

auto can be convenient, very convenient for

auto iter = vec.begin();

But it can also be wrong, when

auto value = copy of proxy

I don't know of another language where

var value = foo()

is correct in some contexts and wrong in others. Surely some
cognitive effort required there.

Daniel






Scott Lurndal

unread,
Dec 13, 2022, 9:59:19 AM12/13/22
to
Keith Thompson <Keith.S.T...@gmail.com> writes:
>sc...@slp53.sl.home (Scott Lurndal) writes:
>> Ike Naar <i...@sdf.org> writes:
>>>On 2022-12-12, Scott Lurndal <sc...@slp53.sl.home> wrote:
>>>> long seed = random(); is perfectly readable and self documenting.
>>>
>>>The word choice is a bit unconventional.
>>>A seed is most often used as an initial input to
>>>a random number generator, not as the result of it.
>>
>> It's common to seed a PRNG with a random number. Preferably
>> a true random number.
>
>If you can get a "true random number", you don't need a PRNG
>(unless your source of true random numbers is slow or otherwise
>resource-intensive). But it's rare to be able to get true random
>numbers in the first place.

Well, we do have a TNRG on our chips. And as you point out,
TRNG's are generally quite slow, so they're often used to seed
PRNG's (either hardware based or software based).

>
>> It wasn't uncommon in the early days of unix games to seed
>> the PRNG with the current time in seconds since the Epoch.
>
>Which is hardly random.

Not particuarly, no. But effective for the simple purposes used.

Mut...@dastardlyhq.com

unread,
Dec 13, 2022, 10:58:37 AM12/13/22
to
On Tue, 13 Dec 2022 11:10:47 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Juha Nieminen <nos...@thanks.invalid> wrote:
>> Believe me, by this point in my life I have read enough other people's
>> code to know for a fact that overtly short naming schemes make code harder
>> to understand, not easier.
>
>Not that probably anybody is interested, but anyway, after all that I have
>come up with a few principles when it comes to naming in order to make
>code easier for a third-party (who has never seen the code before) to read:
>
>- Always use full English words instead of contractions and acronyms.
>"return_value" is better than "ret". "error_code" is better than "err".
>"generateRandomValue" is better than "genRandVal". "column_index" is
>better than "i".

Not if you end up with a wall of text like a lot of Java code.

>(An exception is if the contraction or acronym is universally used and
>understood, like "GPS", "HDMI", "cos", "tan", etc.)

'i' is VERY common as an index value in for().

>- Almost always use namespace prefixes when using names inside a
>namespace, even in code that's inside the same namespace. (This is
>because when the namespace appears in the name, it makes it very
>clear that the name is from that namespace and not a function-local
>name, a class member, or a global name somewhere else.)

In that case whats the point of having a namespace at all? You can achieve
exactly the same result C style with function naming. Eg: instead of
mylib::func() you can just call it mylib_func().

daniel...@gmail.com

unread,
Dec 13, 2022, 11:13:47 AM12/13/22
to
On Monday, December 12, 2022 at 11:32:20 AM UTC-5, Ben Bacarisse wrote:
> Juha Nieminen <nos...@thanks.invalid> writes:
>
> But then I like to program (full disclosure: for fun only these days) in
> Haskell which has, to all intents and purposes, a default auto. Types
> are almost always inferred rather than stated.

But in Haskell cases like this can't arise:

std::vector<bool> v = { true,false,true };
auto value = v[1];
value = true;
assert(v[1] == false); // fails

Were Juha were to inherit a C++ code base that made significant use of matrix
libraries, or was written by programmers that had read Scott Meyers' Effective
C++ series, and that was also liberally sprinkled with auto, he would have
to put some effort into convincing himself that it didn't have "auto value =
copy of proxy" landmines.

Daniel

Mut...@dastardlyhq.com

unread,
Dec 13, 2022, 12:16:26 PM12/13/22
to
On Tue, 13 Dec 2022 08:13:37 -0800 (PST)
"daniel...@gmail.com" <daniel...@gmail.com> wrote:
>On Monday, December 12, 2022 at 11:32:20 AM UTC-5, Ben Bacarisse wrote:
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>> But then I like to program (full disclosure: for fun only these days) in
>> Haskell which has, to all intents and purposes, a default auto. Types
>> are almost always inferred rather than stated.
>
>But in Haskell cases like this can't arise:
>
> std::vector<bool> v = { true,false,true };
> auto value = v[1];
> value = true;
> assert(v[1] == false); // fails

This is something I've never thought about. So when does auto default to a
reference? Because if you change that to an int it doesn't assert eg:

std::vector<int> v = { 1,2,3 };
auto value = v[1];
value = 4;
assert(v[1] == 2);

So in the case of bool its taking a reference, but in the case of int its
doing a copy.


daniel...@gmail.com

unread,
Dec 13, 2022, 2:10:37 PM12/13/22
to
On Tuesday, December 13, 2022 at 12:16:26 PM UTC-5, Mut...@dastardlyhq.com wrote:
> On Tue, 13 Dec 2022 08:13:37 -0800 (PST)
> "daniel...@gmail.com" <daniel...@gmail.com> wrote:
> >On Monday, December 12, 2022 at 11:32:20 AM UTC-5, Ben Bacarisse wrote:
> >> Juha Nieminen <nos...@thanks.invalid> writes:
> >>
> >> But then I like to program (full disclosure: for fun only these days) in
> >> Haskell which has, to all intents and purposes, a default auto. Types
> >> are almost always inferred rather than stated.
> >
> >But in Haskell cases like this can't arise:
> >
> > std::vector<bool> v = { true,false,true };
> > auto value = v[1];
> > value = true;
> > assert(v[1] == false); // fails
> This is something I've never thought about. So when does auto default to a
> reference? Because if you change that to an int it doesn't assert eg:

bool isSomething = false;
auto val = isSomething ; // value
auto& ref = isSomething ; // reference

Same as for int.

That isn't the issue here. The issue is that the index operator for std::vector<bool>
returns a proxy rather than the value of a bool. So value1 and value2 in

auto value1 = v[1];

bool value2 = v[1];

are both values, but different. Mutating value1 has side effects, mutating value2 does not.

Daniel


Chris M. Thomasson

unread,
Dec 13, 2022, 4:07:29 PM12/13/22
to
Fwiw, check this shit out, and experiment in race conditions:

https://groups.google.com/g/comp.lang.c++/c/7u_rLgQe86k/m/XiqELOEECAAJ

;^) lol.

Chris M. Thomasson

unread,
Dec 13, 2022, 4:09:49 PM12/13/22
to
Indeed! :^)


> I left that unaddressed because it has nothing to do with
> my point. Once again, examples like yours (with or without the nullptr
> side issues) don't help because, very often, the confusion comes from
> the neutral and unhelpful names rather than the language feature (in
> that case auto) that is being discussed.
>

Humm... Okay, I think that is fair enough.

Juha Nieminen

unread,
Dec 14, 2022, 1:23:23 AM12/14/22
to
Mut...@dastardlyhq.com wrote:
>>- Always use full English words instead of contractions and acronyms.
>>"return_value" is better than "ret". "error_code" is better than "err".
>>"generateRandomValue" is better than "genRandVal". "column_index" is
>>better than "i".
>
> Not if you end up with a wall of text like a lot of Java code.

And there we go again with the length argument.

Length. Does. Not. Matter. What matters is readability.

>>(An exception is if the contraction or acronym is universally used and
>>understood, like "GPS", "HDMI", "cos", "tan", etc.)
>
> 'i' is VERY common as an index value in for().

But since 'i' does not refer to anything specific, it's better and more
readable if you express what you are indexing with it. This is especially
true the more loops there are (they don't even have to be nested).

I honestly cannot understand why you are even opposing that.

>>- Almost always use namespace prefixes when using names inside a
>>namespace, even in code that's inside the same namespace. (This is
>>because when the namespace appears in the name, it makes it very
>>clear that the name is from that namespace and not a function-local
>>name, a class member, or a global name somewhere else.)
>
> In that case whats the point of having a namespace at all? You can achieve
> exactly the same result C style with function naming. Eg: instead of
> mylib::func() you can just call it mylib_func().

If you want to do that, go right ahead.

Juha Nieminen

unread,
Dec 14, 2022, 2:36:21 AM12/14/22
to
Juha Nieminen <nos...@thanks.invalid> wrote:
>>>- Almost always use namespace prefixes when using names inside a
>>>namespace, even in code that's inside the same namespace. (This is
>>>because when the namespace appears in the name, it makes it very
>>>clear that the name is from that namespace and not a function-local
>>>name, a class member, or a global name somewhere else.)
>>
>> In that case whats the point of having a namespace at all? You can achieve
>> exactly the same result C style with function naming. Eg: instead of
>> mylib::func() you can just call it mylib_func().
>
> If you want to do that, go right ahead.

In fact, I have noticed a rather interesting psychological phenomenon
related to this.

Many C++ programmers will fight tooth and nail to defend their practice
of not writing namespace prefixes and the use of 'using' to allow them
to do that... and the exact same people never, ever, ever complaining
about having to write prefixes in names declared in many C libraries.

They hate the guts of namespace prefixes, but they have zero problems
if the prefix is actually in the names themselves, separated with an
underscore instead of ::.

Why? Your guess is as good as mine. I could present some shaky
psychological hypotheses, but ultimately I have no idea.

So, in this sense, it's actually *better* to attach the namespace to
the names themselves (with an underscore) because that will stop people
from going their way to avoid writing those prefixes, and their code
will automatically become more readable, and they will stop complaining
about the namespace prefixes. Take advantage of this curious psychological
phenomenon.

Juha Nieminen

unread,
Dec 14, 2022, 3:38:40 AM12/14/22
to
Juha Nieminen <nos...@thanks.invalid> wrote:
> During the last few years I have had to read an inordinate amount of
> code written by other people. It has really given me a big insight on
> what makes code more and less readable and understandable. For example,
> I could write an entire book on naming conventions alone, and how they
> can make the code so much more readable, or make it almost inscrutable.

I am reminded of this painful fact right today because I am, once again,
reviewing code written by other people. Code that's full of cryptic
inscrutable acronyms and abbreviations that make it infuriatingly hard
to understand what the code is doing.

The problem that the vast majority of programmers have is that when they
are writing code it's extremely clear *to them* what each variable means
and what its role is. However, to a third-party reader who is reading the
code for the first time it's not necessarily so.

The second problem is that people, for some reason, instinctively want to
write names that are as short as possible, as contracted and abbreviated
as possible, as compressed as possible, just to save typing a few
characters.

The problem is that when they are writing some kind of algorithm, the
algorithm itself, and each variable, is clear to the programmer who is
writing the code, but may not be clear at all to a third-party reader.

Thus you end up with cryptic acronyms like "tpl" and "tpr" and the like.
What are those supposed to mean? Maybe "l" stands for "left" and "r"
stands for "right"?

Turns out that they are supposed to stand for "test point left" and
"test point right". Finding that out is extra difficult because of the
code that initializes them is likewise cryptic, something along the
lines of "tpl = l.p;" which says nothing. What's with this obsession
with brevity? It makes code needlessly inscrutable and cryptic for
absolutely no benefit.

There's literally no reason why those acronyms couldn't be fully spelled
out, using full English words. "test_point_left" and "test_point_right"
are so much more readable and understandable. They immediately tell the
reader what they are supposed to be, and the reader doesn't have to try
to solve the puzzle of what "tpl" stands for by trying to decipher the
rest of the likewise-cryptic code.

Some people will still oppose this, for some reason. But you cannot
change what I am seeing. You are not going to make this code more readable
no matter how many times you repeat that the cryptic acronyms are
actually the ones that are more readable.

Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 4:33:57 AM12/14/22
to
On Tue, 13 Dec 2022 11:10:27 -0800 (PST)
IOW the auto type can differ from expectations.

TBH I've always avoided vector<bool> because of its specialisation. This is
another reason not to use it.


Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 4:35:43 AM12/14/22
to
On Wed, 14 Dec 2022 06:23:05 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Mut...@dastardlyhq.com wrote:
>>>- Always use full English words instead of contractions and acronyms.
>>>"return_value" is better than "ret". "error_code" is better than "err".
>>>"generateRandomValue" is better than "genRandVal". "column_index" is
>>>better than "i".
>>
>> Not if you end up with a wall of text like a lot of Java code.
>
>And there we go again with the length argument.
>
>Length. Does. Not. Matter. What matters is readability.

Clearly you've not worked with much Java code.

>>>(An exception is if the contraction or acronym is universally used and
>>>understood, like "GPS", "HDMI", "cos", "tan", etc.)
>>
>> 'i' is VERY common as an index value in for().
>
>But since 'i' does not refer to anything specific, it's better and more

It doesn't need to, its simply an index counter. Everyone knows it as an
index counter.

>I honestly cannot understand why you are even opposing that.

Long winded names are as bad as names that are meaningless.

>>>- Almost always use namespace prefixes when using names inside a
>>>namespace, even in code that's inside the same namespace. (This is
>>>because when the namespace appears in the name, it makes it very
>>>clear that the name is from that namespace and not a function-local
>>>name, a class member, or a global name somewhere else.)
>>
>> In that case whats the point of having a namespace at all? You can achieve
>> exactly the same result C style with function naming. Eg: instead of
>> mylib::func() you can just call it mylib_func().
>
>If you want to do that, go right ahead.

Its exactly what you're doing except you don't seem to realise it.

Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 4:44:13 AM12/14/22
to
On Wed, 14 Dec 2022 07:36:04 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Juha Nieminen <nos...@thanks.invalid> wrote:
>>>>- Almost always use namespace prefixes when using names inside a
>>>>namespace, even in code that's inside the same namespace. (This is
>>>>because when the namespace appears in the name, it makes it very
>>>>clear that the name is from that namespace and not a function-local
>>>>name, a class member, or a global name somewhere else.)
>>>
>>> In that case whats the point of having a namespace at all? You can achieve
>>> exactly the same result C style with function naming. Eg: instead of
>>> mylib::func() you can just call it mylib_func().
>>
>> If you want to do that, go right ahead.
>
>In fact, I have noticed a rather interesting psychological phenomenon
>related to this.
>
>Many C++ programmers will fight tooth and nail to defend their practice
>of not writing namespace prefixes and the use of 'using' to allow them
>to do that... and the exact same people never, ever, ever complaining
>about having to write prefixes in names declared in many C libraries.

Err, because there's no choice with C?

>They hate the guts of namespace prefixes, but they have zero problems
>if the prefix is actually in the names themselves, separated with an
>underscore instead of ::.
>
>Why? Your guess is as good as mine. I could present some shaky
>psychological hypotheses, but ultimately I have no idea.
>
>So, in this sense, it's actually *better* to attach the namespace to
>the names themselves (with an underscore) because that will stop people
>from going their way to avoid writing those prefixes, and their code
>will automatically become more readable, and they will stop complaining
>about the namespace prefixes. Take advantage of this curious psychological
>phenomenon.

You need to look in the mirror. *You* are the one who uses the namespace name
*inside* itself. How is mynamespace::func() any different from writing
mynamespace_func()?

Most sensible C++ devs would just write func() inside that namespace which
is the whole point of namespaces. Why did you think they were invented in
the first place? Bjorn could have just gone with long function prefixes.

Ben Bacarisse

unread,
Dec 14, 2022, 6:54:41 AM12/14/22
to
"daniel...@gmail.com" <daniel...@gmail.com> writes:

> On Monday, December 12, 2022 at 11:32:20 AM UTC-5, Ben Bacarisse wrote:
>> Juha Nieminen <nos...@thanks.invalid> writes:
>>
>> But then I like to program (full disclosure: for fun only these days) in
>> Haskell which has, to all intents and purposes, a default auto. Types
>> are almost always inferred rather than stated.
>
> But in Haskell cases like this can't arise:
>
> std::vector<bool> v = { true,false,true };
> auto value = v[1];
> value = true;
> assert(v[1] == false); // fails

That "fail" is so obvious that I think there must be a better example of
something that will baffle the reader.

Is a wide-spread idiom in which some aggregate accessory (like
operator[]) really returns something that behaves like a reference but
which is defeated by the use of auto?

> Were Juha were to inherit a C++ code base that made significant use of matrix
> libraries, or was written by programmers that had read Scott Meyers' Effective
> C++ series, and that was also liberally sprinkled with auto, he would have
> to put some effort into convincing himself that it didn't have "auto value =
> copy of proxy" landmines.

Can you give a cut-down example? I can't shake the feeling that the
problem might not be with auto, but with the idiom that is defeated by
using auto. (Not that I want to defend all uses of auto. C++'s types
are so potentially baroque and open to abuse that knowing the exact type
might very well be beneficial at times.)

--
Ben.

Juha Nieminen

unread,
Dec 14, 2022, 7:19:54 AM12/14/22
to
Mut...@dastardlyhq.com wrote:
> You need to look in the mirror. *You* are the one who uses the namespace name
> *inside* itself. How is mynamespace::func() any different from writing
> mynamespace_func()?

In the latter the prefix is mandatory, in the former it's not.

With the prefix it becomes a lot clearer where that func() is, and thus
the code is much easier to understand.

> Most sensible C++ devs would just write func() inside that namespace which
> is the whole point of namespaces. Why did you think they were invented in
> the first place? Bjorn could have just gone with long function prefixes.

Bjarne. And he isn't a Perfect God who is always right.

Namespaces can have other uses, such as bringing the names of one namespace
into another (which, in a way, is a bit like "inheriting" the other
namespace).

Juha Nieminen

unread,
Dec 14, 2022, 7:28:41 AM12/14/22
to
Mut...@dastardlyhq.com wrote:
>>> 'i' is VERY common as an index value in for().
>>
>>But since 'i' does not refer to anything specific, it's better and more
>
> It doesn't need to, its simply an index counter. Everyone knows it as an
> index counter.

What's so hard to understand in the fact that the name 'i' does not tell
me _anything_ about what it's going to be used for? And that if it's
named so that it tells what it's going to index, it makes the for loop
line immediately clearer, because it's directly telling me what we
are looping. Also, if the amount of code in the loop is even slightly
long, a quick visual scan will reveal all the instances of eg.
"column_index" a lot easier than an "i" buried somewhere inside
some square brackets at random places.

This becomes *especially* important with nested loop. You wouldn't
believe how significantly clearer it is when each loop variable is
named clearly after what it's going to index, compared to if they
are just named 'i', 'j' and 'k'.

I honestly cannot understand what's so controversial about this.
It should be quite self-evident: When you express what it's being
used for, it's much easier to understand than if it's just a
short generic name that says nothing.

>>I honestly cannot understand why you are even opposing that.
>
> Long winded names are as bad as names that are meaningless.

That's just a completely asinine assertion.

If long-winded names are bad, then why do you use long words when
you write English? Why don't you contract every word you use?

You use full English words because if you were to contract every
word your text would become illegible. Why is code any different?

I just find it baffling how this seems to be so controversial.
*Tell what you are doing* in your code. Don't make it cryptic and
obscure for no reason. This should be good programming 101.
We are not writing code for the obfuscated C code contest.

>>> In that case whats the point of having a namespace at all? You can achieve
>>> exactly the same result C style with function naming. Eg: instead of
>>> mylib::func() you can just call it mylib_func().
>>
>>If you want to do that, go right ahead.
>
> Its exactly what you're doing except you don't seem to realise it.

I fail to see the problem.

David Brown

unread,
Dec 14, 2022, 8:12:12 AM12/14/22
to
On 14/12/2022 08:36, Juha Nieminen wrote:
> Juha Nieminen <nos...@thanks.invalid> wrote:
>>>> - Almost always use namespace prefixes when using names inside a
>>>> namespace, even in code that's inside the same namespace. (This is
>>>> because when the namespace appears in the name, it makes it very
>>>> clear that the name is from that namespace and not a function-local
>>>> name, a class member, or a global name somewhere else.)
>>>
>>> In that case whats the point of having a namespace at all? You can achieve
>>> exactly the same result C style with function naming. Eg: instead of
>>> mylib::func() you can just call it mylib_func().
>>
>> If you want to do that, go right ahead.
>
> In fact, I have noticed a rather interesting psychological phenomenon
> related to this.
>
> Many C++ programmers will fight tooth and nail to defend their practice
> of not writing namespace prefixes and the use of 'using' to allow them
> to do that... and the exact same people never, ever, ever complaining
> about having to write prefixes in names declared in many C libraries.

Really?

I wonder if you have very odd colleagues, or if you interpret things
differently from myself (and apparently some others in this thread).

I use "using" locally in functions when it makes code simpler and
clearer, because it makes names shorter and has less clutter. It also
makes it clearer that I am "using" a particular imported namespace. If
I have a namespace called "display", and I am writing a function that
uses the display, it is a /good/ thing to write "using namespace
display;" in that function. It is a /good/ thing to write "clear();" or
"get_dimensions()" rather than "display::clear();" and
"display::get_dimensions()".

Obviously if there is ambiguity, you need to use namespace prefixes.

In C, people /do/ grumble about long and awkward names with no scoping.
They minimise the problem by using short abbreviations for their
prefixes, and they don't complain too much because it is pointless to
complain too much since there is no alternative.

>
> They hate the guts of namespace prefixes, but they have zero problems
> if the prefix is actually in the names themselves, separated with an
> underscore instead of ::.
>

As you have been doing throughout this thread, you are wildly exaggerating.

People don't like having to write long prefixes when it is obvious from
the context of the code which library or set of identifiers you are
using. They don't like it in C, and they don't like it in C++. The
difference is that in C you are stuck with using it, while in C++ you
have multiple options for structured and scoped naming - and sometimes
you have the option of reducing the verbosity by a "using" clause.

> Why? Your guess is as good as mine. I could present some shaky
> psychological hypotheses, but ultimately I have no idea.
>
> So, in this sense, it's actually *better* to attach the namespace to
> the names themselves (with an underscore) because that will stop people
> from going their way to avoid writing those prefixes, and their code
> will automatically become more readable, and they will stop complaining
> about the namespace prefixes. Take advantage of this curious psychological
> phenomenon.

I believe this "curious psychological phenomenon" is primarily in your
own mind, not in the minds of other programmers.

David Brown

unread,
Dec 14, 2022, 8:16:48 AM12/14/22
to
Yes, the problem here is that a std::vector<bool> behaves significantly
differently from all other std::vector types. The intention of the STL
(as it was called in those days) developers was to make something that
is efficient, compact, and as simple to use as other vector types. They
did a reasonable job, but the result is inconsistent and surprising in
some ways. I would much preferred inefficiency and consistency, and a
separate type ("bit_vector") for compactness.


David Brown

unread,
Dec 14, 2022, 8:23:19 AM12/14/22
to
On 14/12/2022 09:38, Juha Nieminen wrote:
> Juha Nieminen <nos...@thanks.invalid> wrote:
>> During the last few years I have had to read an inordinate amount of
>> code written by other people. It has really given me a big insight on
>> what makes code more and less readable and understandable. For example,
>> I could write an entire book on naming conventions alone, and how they
>> can make the code so much more readable, or make it almost inscrutable.
>
> I am reminded of this painful fact right today because I am, once again,
> reviewing code written by other people. Code that's full of cryptic
> inscrutable acronyms and abbreviations that make it infuriatingly hard
> to understand what the code is doing.
>
> The problem that the vast majority of programmers have is that when they
> are writing code it's extremely clear *to them* what each variable means
> and what its role is. However, to a third-party reader who is reading the
> code for the first time it's not necessarily so.
>
> The second problem is that people, for some reason, instinctively want to
> write names that are as short as possible, as contracted and abbreviated
> as possible, as compressed as possible, just to save typing a few
> characters.
>

I also happen to be working with code written by others today. The code
is a pile of dodo doo-doo. Most of the identifiers have long and
expressive names, but it is still crap code, and still incomprehensible.
I don't think shorter names would have helped much, but they might
have made the code a little more readable in some places - code that is
logically one line would not have been spread over two physical lines.

Still, naming choices are not in the top ten problems with the code.

I really think if acronyms and short names are the biggest issue you
have with other people's code, either it is very unusual code or you are
missing the most important problems, such as poor structure or overly
long functions.


Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 11:24:35 AM12/14/22
to
On Wed, 14 Dec 2022 12:19:37 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Mut...@dastardlyhq.com wrote:
>> You need to look in the mirror. *You* are the one who uses the namespace
>name
>> *inside* itself. How is mynamespace::func() any different from writing
>> mynamespace_func()?
>
>In the latter the prefix is mandatory, in the former it's not.

No shit. Well done on completely missing my point.

>With the prefix it becomes a lot clearer where that func() is, and thus
>the code is much easier to understand.

So why not just use prefixes instead of namespaces?

>> Most sensible C++ devs would just write func() inside that namespace which
>> is the whole point of namespaces. Why did you think they were invented in
>> the first place? Bjorn could have just gone with long function prefixes.
>
>Bjarne. And he isn't a Perfect God who is always right.
>
>Namespaces can have other uses, such as bringing the names of one namespace
>into another (which, in a way, is a bit like "inheriting" the other
>namespace).

But you'd write the fully expressed name anyway, right?

Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 11:30:22 AM12/14/22
to
On Wed, 14 Dec 2022 12:28:24 -0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>Mut...@dastardlyhq.com wrote:
>>>> 'i' is VERY common as an index value in for().
>>>
>>>But since 'i' does not refer to anything specific, it's better and more
>>
>> It doesn't need to, its simply an index counter. Everyone knows it as an
>> index counter.
>
>What's so hard to understand in the fact that the name 'i' does not tell
>me _anything_ about what it's going to be used for? And that if it's

Its convention. 'i' has been the top level index counter since 1980s BASIC.
You'll probably find it used as an index var in for() in just about every large
C and C++ program ever written.

>This becomes *especially* important with nested loop. You wouldn't
>believe how significantly clearer it is when each loop variable is
>named clearly after what it's going to index, compared to if they
>are just named 'i', 'j' and 'k'.

Clearer for you maybe. For me i, j and k would be perfectly clear.

>I honestly cannot understand what's so controversial about this.

Nothing. But I can't understand why you seem to think your personal preferences
are the True Way. Though then you're not alone in that.

>It should be quite self-evident: When you express what it's being
>used for, it's much easier to understand than if it's just a
>short generic name that says nothing.

Speak for yourself.

>> Long winded names are as bad as names that are meaningless.
>
>That's just a completely asinine assertion.

Go read some Java.

>If long-winded names are bad, then why do you use long words when
>you write English? Why don't you contract every word you use?

I guess you've never used SMS.

>You use full English words because if you were to contract every
>word your text would become illegible. Why is code any different?

A lot of common words in English are short, eg 'a', 'an', 'the'. Same in most
european languages (and probably others). And russian dispensed with the
definate and indefinate articles altogether.

>I just find it baffling how this seems to be so controversial.
>*Tell what you are doing* in your code. Don't make it cryptic and
>obscure for no reason. This should be good programming 101.
>We are not writing code for the obfuscated C code contest.

*sigh*

Michael S

unread,
Dec 14, 2022, 11:36:17 AM12/14/22
to
On Wednesday, December 14, 2022 at 3:23:19 PM UTC+2, David Brown wrote:
> On 14/12/2022 09:38, Juha Nieminen wrote:
> > Juha Nieminen <nos...@thanks.invalid> wrote:
> >> During the last few years I have had to read an inordinate amount of
> >> code written by other people. It has really given me a big insight on
> >> what makes code more and less readable and understandable. For example,
> >> I could write an entire book on naming conventions alone, and how they
> >> can make the code so much more readable, or make it almost inscrutable.
> >
> > I am reminded of this painful fact right today because I am, once again,
> > reviewing code written by other people. Code that's full of cryptic
> > inscrutable acronyms and abbreviations that make it infuriatingly hard
> > to understand what the code is doing.
> >
> > The problem that the vast majority of programmers have is that when they
> > are writing code it's extremely clear *to them* what each variable means
> > and what its role is. However, to a third-party reader who is reading the
> > code for the first time it's not necessarily so.
> >
> > The second problem is that people, for some reason, instinctively want to
> > write names that are as short as possible, as contracted and abbreviated
> > as possible, as compressed as possible, just to save typing a few
> > characters.
> >
> I also happen to be working with code written by others today. The code
> is a pile of dodo doo-doo.

"Hell is other people's code"

Udo Steinbach

unread,
Dec 14, 2022, 11:50:56 AM12/14/22
to
Am 2022-12-12 um 18:17 schrieb Scott Lurndal:
> I'll take 'rval' over "returnValue" every time.

And why not „CurrentTime“? I name variables after their content, not their
function. One look on the return statement says the reader what it does
return.
What do you do if you have two return statements in which you return two
different variables, name them rval1 and rval2? Or do you assign the
second to rval before return?
--
Fahrradverkehr in Deutschland: http://radwege.udoline.de/
GPG: A245 F153 0636 6E34 E2F3 E1EB 817A B14D 3E7E 482E

Scott Lurndal

unread,
Dec 14, 2022, 11:50:58 AM12/14/22
to
Mut...@dastardlyhq.com writes:
>On Wed, 14 Dec 2022 12:28:24 -0000 (UTC)
>Juha Nieminen <nos...@thanks.invalid> wrote:
>>Mut...@dastardlyhq.com wrote:
>>>>> 'i' is VERY common as an index value in for().
>>>>
>>>>But since 'i' does not refer to anything specific, it's better and more
>>>
>>> It doesn't need to, its simply an index counter. Everyone knows it as an
>>> index counter.
>>
>>What's so hard to understand in the fact that the name 'i' does not tell
>>me _anything_ about what it's going to be used for? And that if it's
>
>Its convention. 'i' has been the top level index counter since 1980s BASIC.

How about 1960s Basic? Or Fortran 66, for that matter, where I,J, K, L, M and N are
implictly integer.

Scott Lurndal

unread,
Dec 14, 2022, 12:14:13 PM12/14/22
to
Udo Steinbach <tras...@udoline.de> writes:
>Am 2022-12-12 um 18:17 schrieb Scott Lurndal:
>> I'll take 'rval' over "returnValue" every time.
>
>And why not „CurrentTime“? I name variables after their content, not their
>function. One look on the return statement says the reader what it does
>return.
>What do you do if you have two return statements in which you return two
>different variables, name them rval1 and rval2? Or do you assign the
>second to rval before return?

* @param iocb The IOCB describing the WRITE operation.
* @returns false if the operation succeeded, true for failure.
*/
bool
c_uniline_dlp::ocs_write(c_iocb *iocb)
{
uint8 cmd = iocb->get_op_var1();
bool rval = false;

switch (cmd) {
case IOD_OCSWRITE_WC:
lock();
rval = ocs_write_control(iocb);
unlock();
break;
case IOD_OCSWRITE_LOAD_FIRMWARE:
rval = load_firmware(iocb);
break;
case IOD_OCSWRITE_WC_RC:
case IOD_OCSWRITE_WC_RC_INH_TO:
lock();
u_write_failed = false;
u_write_complete = false;
rval = ocs_write_control(iocb);
if (rval) {
while (!u_write_complete) {
bool timeout = u_flip_read.timed_wait(&u_lock, u_write_timeout);
if (timeout && ((cmd & 1) == 0)) {
u_write_failed = true;
set_rd(iocb, IOT_WITH_EXCEPTIONS, RD1_OCS_TIMEOUT);
break;
}
}
if (!u_write_failed) {
stc_read_control(iocb, cmd&1);
}
}
unlock();
rval = false;
break;
default:
d_logger->log("%s OCS Unsupported write op '%1.1lx'\n",
u_dlp_name, iocb->get_op_var1());
set_rd(iocb, IOT_WITH_EXCEPTIONS, RD_DESCRIPTOR_ERROR);
break;
}

return rval;
}

Given multithreaded code and the required synchronization, it is wise
to limit the number of early 'return' statements in a function.

Mut...@dastardlyhq.com

unread,
Dec 14, 2022, 12:16:33 PM12/14/22
to
My programming experience only goes back to the 80s but I'll take your word
for it :)

daniel...@gmail.com

unread,
Dec 14, 2022, 12:40:52 PM12/14/22
to
On Wednesday, December 14, 2022 at 6:54:41 AM UTC-5, Ben Bacarisse wrote:
> "daniel...@gmail.com" <daniel...@gmail.com> writes:
>
> > But in Haskell cases like this can't arise:
> >
> > std::vector<bool> v = { true,false,true };
> > auto value = v[1];
> > value = true;
> > assert(v[1] == false); // fails

> That "fail" is so obvious that I think there must be a better example of
> something that will baffle the reader.

Is it so obvious? I would have thought a typical C++ programmer
would expect bare auto to never deduce a reference. But here
it seemingly does.

In any case, the example wasn't designed to baffle the reader,
but to illustrate the problem of using auto in conjunction with functions
returning proxy values invoking only the standard library.

>
> Is a wide-spread idiom in which some aggregate accessory (like
> operator[]) really returns something that behaves like a reference but
> which is defeated by the use of auto?

It certainly is in numerical libraries such as Eigen and Armadillo , which use
return proxies extensively, particularly for functions and operators returning matrices
(to avoid unnecessary copies). Elsewhere, in pre-auto days Scott Meyers popularized
the use of proxy return types in his series of Effective C++ books. They're not
that rare, including as noted one instance in the standard library.

> > Were Juha were to inherit a C++ code base that made significant use of matrix
> > libraries, or was written by programmers that had read Scott Meyers' Effective
> > C++ series, and that was also liberally sprinkled with auto, he would have
> > to put some effort into convincing himself that it didn't have "auto value =
> > copy of proxy" landmines.

> Can you give a cut-down example?

See link below. Regarding the potential landmines of using proxy objects ,
ones I've seen include expecting a value type but getting reference semantics
(as illustrated above), acquiring a complex proxy object where member
functions perform expensive lookups for every call, and acquiring objects
that hold pointers to memory that is past the continuation point.

>I can't shake the feeling that the
> problem might not be with auto, but with the idiom that is defeated by
> using auto.

As noted, the idiom is firmly entrenched in numerical libraries, particularly
in implementations of expression templates.

Proxies and auto don't interact well, because auto exposes aspects of
the type that were meant to stay hidden. There have been suggestions
for a language change, where the auto in auto v = foo() or auto& v = foo()
can be deduced as the value type, even if foo() returns a proxy value, see
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0672r0.pdf.

In the meantime, it might be prudent to exercise some caution in the use of auto,
and not to blindly use it everywhere.

Daniel


Udo Steinbach

unread,
Dec 14, 2022, 12:43:47 PM12/14/22
to
Am 2022-12-13 um 09:42 schrieb David Brown:
> calculate_average_of_vector_of_ints() {
>     int the_size_of_the_vector_of_ints_to_average

I love practical examples used to support the opposite practical point of view.

> Are you seriously suggesting that the first version is "clearer"

Cheap straw man.
int CalcAverage(std::vector<int> Throughput) {
{ int Sum= 0;
for (int Current : Throughput)
Sum += Current;
return Sum / Throughput.size();

Paavo Helde

unread,
Dec 14, 2022, 1:01:33 PM12/14/22
to
Ant the reason to not use a C++-style RAII lock is ...? Nostalgy for C?



Scott Lurndal

unread,
Dec 14, 2022, 1:12:55 PM12/14/22
to
1) the code was written quite some time ago, C++ 2.1 era.

2) I prefer to keep critical sections as small as possible,
particularly in CPU-bound multithreaded applications like this one.

3) I've found that using RAII prevents the programmer from actually thinking
and reasoning about the critical section; instead they just blindly lock
an entire function and all the functions called from it (which may acquire
locks of their own, and may even recurse).

David Brown

unread,
Dec 14, 2022, 2:01:48 PM12/14/22
to
Or 1970's Forth, where I and J are standard words built into the
language as the way to access loop counters.


Udo Steinbach

unread,
Dec 14, 2022, 2:03:31 PM12/14/22
to
Am 2022-12-12 um 09:49 schrieb David Brown:
> when the exact type matters

This is the keyword. A security man who has to audit your code needs the
exact type of everything and you have to pay for every over-shorting,
every ambiguity, and for every single auto. Maybe that your collegue knows
about the types and names. But he or you pays with time, if not, if he
misunderstands, overlooks a little thing.

http://blog.fefe.de/?ts=a0cf97c9 about C++ auto
„Then the poor auditor has to run after each crappy line one by one and
derive the types himself.“

David Brown

unread,
Dec 14, 2022, 2:06:41 PM12/14/22
to
On 14/12/2022 18:43, Udo Steinbach wrote:
> Am 2022-12-13 um 09:42 schrieb David Brown:
>> calculate_average_of_vector_of_ints() {
>>     int the_size_of_the_vector_of_ints_to_average
>
> I love practical examples used to support the opposite practical point of view.
>
>> Are you seriously suggesting that the first version is "clearer"
>
> Cheap straw man.
> int CalcAverage(std::vector<int> Throughput) {
> { int Sum= 0;
> for (int Current : Throughput)
> Sum += Current;
> return Sum / Throughput.size();
> }

That's shorter names, that are easier to read. But I don't think they
are very good choices of names. It's a very general function, and yet
the way you have written it suggests it is only for calculating average
throughput. If that is the case, then the function name is bad - if it
is not the case, then the parameter name is bad.


It is loading more messages.
0 new messages