If you haven’t seen the previous post, I’ve posted a
question of what style would you prefer (I’ve simplified it a bit here,
for the original, go for the link above):
(A) | (B)
|
if (ratio < 1.5) { | result = (ratio < 1.5) ? 1.0 :
result = 1.0; | (ratio < 2.0) ? 1.5 :
} else if (ratio < 2.0) { | (ratio < 3.0) ? 3.0 :
result = 1.5; | /* otherwise */ ratio;
} else if (ratio < 2.5) { |
result = 2.0; |
} else if (ratio < 3.0) { |
result = 3.0; |
} else { |
result = ratio; |
}
As expected, people are split into two similarly sized groups. It is
a matter of style after all.
Neither of these is better, but they both have their pros and cons.
Lets see what we have collected so far.
Firstly, lets deal with the elephants in the room:
- Is this an academic question? (as suggested by
krake)
Yes and no. Yes, because it is not really that important - people
will continue using what they used before. No, because it might
influence the different aspects of the resulting code. (see below)
- You can use if-return format: (suggested by
cyber_fusion)
if (...) return ...;
if (...) return ...;
...
This seems to be a popular variant of (A) when the purpose of the
result variable is to be returned from the function we’re in (as it was
the case in the original post). It does not work in other cases.
While it is a good approach (and preferred by a significant number of
people), there was one statement for it, that is not correct -
(Alex) “it shows structure, it will not execute if statements after
a successful one”. All the proposals behave the same - neither
executes statements after the first successful one.
The issue some people pointed out is the lack of braces for the if
body which is frowned upon by a significant number of coding styles used
across the world. If somebody questions why would missing braces would
ever be a problem, just search for the ‘apple goto fail’. When you add
braces, the solution stops being as visually attractive.
Now, we can start with the reasons people wrote for one or the other.
In no particular order, to avoid the trap of actually counting pros and
cons.
(shamaz) The big difference here is that the 2nd solution is
ONE statement. This means that it’s less simple to debug : you won’t see
which branch is chosen (similar comment by Morten)
It is a single statement, but it has multiple sequence points[↗] (or whatever
they are called in the new standard). The same sequence points an
if/else construct does. So it will show up (tested in gcc+gdb1) as
separate steps while debugging2. You will be able to see where you left
the statement.
Edit: 1 clang does not create the same debugging
info, so it does treat it as one execution step.
2 It has a big uglier debugging output, but still is quite
usable.
(Lihnell) I’d like to add that putting the else in a comment
for readability is a clear indicator that the language used is not
suitable to the person using it
I do agree. It essentially boils down to the fact that ?: syntax (for
this) is not something people are used to. So adding ‘else’ or
‘otherwise’ is a nice way to make it more readable.
(konqoro) I guess it was how we were told to better
understand the if-else statements.
There were a few similar comments to this one.
Yes, if-else approach is ubiquitous, and therefore understandable by
everyone. IMO, it is the strongest reason for going for it - people are
not used to (B) even if (Jeff) “the notation fades into the background,
and the structure of the actual operation pops out”.
(dhardy) I find the second much easier to read. My
preferences are (a) avoid re-assigning variables
Thanks to some pure functional languages like haskell, the concept of
immutability started to spread out to other paradigms. The second
approach is also usable in C++11 constexpr functions, while the first
one will be allowed in C++14.
One of the approaches to make the result variable const for the (A)
variant would be to use lambda-initialization, thus localising the
mutable variable inside the lambda. Like:
const double result = [] { ... }();
(Alex Elsayed) I doubt you care overmuch, but PHP will not do
what you expect on the second one
You are right that I do not. But, this is a useful information for
the future - if I get to hack on some PHP code. Thanks!
(shamaz) For the 2nd solution, if someone try to format your
code automatically with his IDE, it may become hard to
read.
Yes, unfortunately. I’ve tested it with clang-format and it
essentially killed it. I guess if it became a common idiom, formatters
would learn to deal with it. :)
Epilogue:
Personally, I prefer the second option although I don’t use it that
often mainly because it is not that common and people are not used to
it.
I do prefer it on the technical grounds, though. It is perfect for
const initialization / constexpr functions, the syntax stops you making
code-evolution mistakes similar to the ‘goto fail’, and different
mistakes that the original code (which inspired me to write this) had.
(the original code was posted for half an hour in the previous post, but
I decided to edit it to show only the styling differences, without other
issues)