Reading this code almost makes me want to think about how differently I review Java than C or C++.
ch = ++index < strlen ? str.charAt(index) : 0;
If I saw that code scattered across in some java code, I would immediately be like - "rewrite please".
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.
The real question is why C/C++ programmers accept code like that. You can write that same code in an easier-to-follow way, and the compiler will turn it into an identical binary.
Frameworks produced by Windows dev team are a very good example of that.
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.
People who care about correctness wouldn't be using C/C++ in the first place. The culture of those languages is performance above all else, and it only gets worse as more and more "moderates" move to memory-safe languages, leaving only the extremists left.
That is not an informed opinion at all. The C++ people I know ALL care about correctness... That's why they use C++. They want to make sure it's done correctly, and not left to some node package that barely works.
Agree, especially as there's so little upside to writing it this way. It isn't going to run any faster. The style emphasises code-density over readability, but density is only a virtue when it aids readability.
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.
The above is an extension function(which is basically a member function of class not written in that class), which has an implicit `this` parameter. In other words `length` is actually `this.length`, just as it would be in a regular method.
To me, the original C-style code looks nicer than the Java.
C++:
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 suppose the main point I was trying to convey is that the code snippet gopalv quoted is not ugly because it's C-like. That ternary expression doesn't appear in the original C++ implementation at all. Many of the things people are complaining about—like relying on the return value of a prefix increment—are only in the Java version.
As someone who writes both C++ and C# I disagree around writing C/C++ in this way. (I am talking specifically about the side effect to 'index', not the use of a tertiary operator which is fine here)
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
That throws an exception though, while this code is trying to return 0. The java "fix" would be to add a charAtOrDefault(), but that doesn't seem to exist.
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?
Agreed. Though catching and handling that exception maybe more performant if majority of those indexes are within the bounds of the array.
>> 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
(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.
I disagree, why exactly would it need to be re-written because it's in Java? Does the language matter at all? To me this piece of code is concise, I immediately recognized it as a bounds check. If you re-write this to add braces, newlines, the if statement... just creates more cognitive load in favor of? To me this little line is perfect, it does exactly what it is supposed to do and it doesn't hide its intent.
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...