Code should be written for humans.
They could produce something that looks like Qt, OWL/VCL, or nowadays .NET like but in C++.
Instead they produce libraries where one is forced to use C low level details, mixed with Win32 and COM pointer handling and casts everywhere, not even MFC escapes it.
Not to count how many interactions of COM smart pointers that have come up with since COM exists.
C++/CX looked like they finally learned their way and would offer something similar to C++ Builder, but no that wasn't meant for us to enjoy it.
So now anyone doing UWP with C++, gets to manually edit IDL files without tooling support, and merge the generated files manually.
I really don't get their macho developer culture.
In retrospect, do you feel it was it a bad idea to not use a heavier abstraction?
It was a bad idea versus what other compiler vendors had in their toolbox.
MFC only won because Microsoft is the OS vendor, and Borland lost it trying to fly too high.
Back in the MS-DOS and Windows 3.x very few would use Microsoft compilers, Borland and Watcom were the favourite.
I'm inclined to not recognize that as a distinct culture and rather call it an infectious habit. Auditable, maintainable code is a skill, after all.
let ch = if index < strlen then str.charAt(index) else 0
Eminently readable and less boring than long if/else chains in Python.On a side note, having gotten used to newer languages, an option type sure is a nice thing.
>>> foo = 10
>>> bar = foo if foo > 5 else 0
>>> bar
10
>>> bar = foo if foo < 5 else 0
>>> bar
0"for ch in index:"
reads pretty cleanly to me.
I'd far prefer:
++index;
ch = index < strlen ? str.charAt(index) : 0;
I don't see a good reason to make it a macro, though. index += 1;
if (index < strlen) {
ch = str.charAt(index);
} else {
ch = 0;
}
If I was using kotlin, I'd do it even cleaner: inline fun String.at(index: Int): Char? =
if (index >= 0 && index < length) charAt(index)
else null
[...]
index += 1
ch = str.at(index) ?: 0;
The bytecode is exactly the same, but I’d argue it’s much cleanerC++:
bool found_minus = (*p == '-');
bool negative = false;
if (found_minus) {
++p;
negative = true;
if (!is_integer(*p)) { // a negative sign must be followed by an integer
return nullptr;
}
}
Java: int strlen = str.length();
if (strlen == 0) {
throw new NumberFormatException("empty String");
}
int index = 0;
char ch = str.charAt(index);
boolean negative = false;
if (ch == '-') {
negative = true;
ch = ++index < strlen ? str.charAt(index) : 0;
if (ch == 0) {
throw new NumberFormatException("'-' cannot stand alone");
}
}I have seen far too many bugs creep in this way. I feel like C/C++ induce a desire to keep the code as short as possible and being 'clever'; even I often feel the need to do that in C++ when I am happy to write a more readable version in other programming languages.
The bugs are also hard to spot when skimming through the code: When there's a lot of code you will often miss the ++ on the 'index' as it's a long line compared to having '++index' on its own line.
Another good 'pet peeve' of mine is the following construct:
for(int i = 10; i--;)
// Do something until 'i' reaches 0
So many off-by-one errors...The source of charAt is also interesting because it manually bounds checks while the array access into the underlying char[] has its own bounds check. I'm not sure why having the separate exception is better than letting the array access throw directly?
https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/19fb8f93c...
>> I'm not sure why having the separate exception is better than letting the array access throw directly?
(1) The original String charAt method (Sun/Oracle) had to account for an offset and an index. The exception from the bounds check on the underlying char[] would be misleading/confusing... and therefore the birth of the seperate StringIndexOutOfBoundsException
Source: http://www.docjar.com/html/api/java/lang/String.java.html
(2) Because of the above and for backward compatibility, the OpenJDK is doing the same exception handling... sometimes it pays to review the original source code to get some context and rationale to the OpenJDK version.
But the same code fragment in C would be like - yeah, we need a bounds check, good job, can you make it a macro please.
The java default Float parser was somewhat of a complete perf headache when multi-threading, more than about single core consumption (till jdk8b96 - JDK-7032154), so in the past Hive has shipped with its own strod impl[1] to avoid the central lock in parseDouble.
Also it worked off a raw utf8 byte[] stream, which is more common coming out of a disk file or network serialization rather than a CharSequence.
[1] - https://github.com/apache/hive/blob/4446414f4478091db1eb20bc...