
“No-else-after-return” considered harmful - kinetik
http://blog.mozilla.com/nnethercote/2009/08/31/no-else-after-return-considered-harmful/
======
nostrademons
C++ is not Ocaml, and Mozilla is not random-opensource-project. When you're
contributing to an established project, you follow the conventions there even
if they aren't what you'd consider ideal.

Brendan Eich even said as much in the comments of the bug: he'd rather be
programming in a pure, expression-based manner too, but C++ is not Ocaml. And
for a lot of C++ code, no-else-after-return works reasonably well.

------
xsmasher
I'm with Mozilla.

If I have a function with multiple conditions that cause me to return error /
false / nil, I'd rather not have to nest them all in a series of if/then/else
statements nor combine them into a single more-complicated if condition. I'd
rather write them each as separate if-and-returns, followed by the real meat
of the function.

function updatePlayers{

    
    
      if (charList is empty)
         return false;
    
      if (play is paused)
         return false;
    
      if (char is frozen)
         return false;
    
      //do stuff here
      return true;

}

I think this better spells out the "error" conditions.

~~~
natrius
Guard clauses are a particular case of if statements. I agree with omitting
elses when using guard clauses. A blanket rule that eliminates elses after
returns doesn't make any sense.

~~~
njharman
Blanket rules don't make sense.

------
makecheck
I always go a step further, and use at most one "return" in a function.

I find short-cut "return" statements frustrating for many reasons. For
example, there's a risk that proper cleanup will not always happen, it is
harder to see state and program flow when debugging, and it's no longer simple
to make every-case changes by adding things to the end of the function.
They're really just another type of "goto".

The only "advantages" I can think of are saving a few keystrokes, and having
slightly better performance by not using a variable for the return value. In
my experience, neither of those things has ever mattered.

In other words, I'd do this:

    
    
      <type> result = defaultValue;
      if (condition)
      {
        result = val1;
      }
      else
      {
        result = val2;
      }
      return result;
    

With this approach, there is never anything after the "return", "else" or
otherwise.

~~~
antonovka
Yuueurrgh.

Without early return, you wind up with multiple-nested if statements that make
the code absolutely unreadable. Early return is almost always used as the
error path -- if you need to perform cleanup, then instead of returning, _use
goto_ to jump to a single end-of-function cleanup handler.

There's nothing wrong with using goto for this purpose, and it means I can
actually read -- at a glance -- code that requires more than a few
preconditions at the start of the function.

~~~
makecheck
Functions that have become too complicated _should_ look ugly, so that they're
likely to be split into simpler parts (for true readability).

When making that split, it is also helpful to have relevant cleanup code
nearby: odds are everything is already in the inner block, instead of having
to remove extra code at the end of the function.

~~~
antonovka
That's the usual hand-waving argument (if you need this you're doing it
wrong), but the fact is that even something with three simple preconditions is
quickly rendered unreadable through three nested levels of if statements.

------
olliesaunders
Profoundly unconvinced.

------
psyklic
A minor quibble. He claims that "no-elses" are prone to side-effects and
"error-prone junk". However, "no-elses" are in my opinion as flagrant a crime
as "no-braces" following if statements (which appears to be his style). The
author says that he prefers the _ternary_ operator (a > b ? a : b) to "no-
elses"; however, its use is definitely more error-prone!

------
joecomotion
I prefer to return as early as possible and I dislike unnecessary else
clauses. And unnecessary braces. I especially hate really long functions where
there's only one return but a bunch of baggage and nested conditionals along
the way to pull it off. Like mullr said, only handy if your language doesn't
support guards.

Most of the people who code this way that I've met don't do it b/c they're
trying to be 'pure.' Most of them say it was coding standard some manager
mentioned somewhere else long ago and now they just do it w/o thinking.

------
thristian
On the one hand, this reads like "I prefer functional languages, and want to
twist procedural languages into a form I'm more familiar with". On the other
hand, I do find his re-written example more readable, and I'm not sure if
that's due to my previous exposure to functional programming, some innate
readability bestowed by the functional programming style, or just the fact
that this particular code was rewritten by someone who wanted to make it a
publishable example (as opposed to just getting it to work).

------
apgwoz
What's his argument about purity here? His examples rely on global state which
is inherently impure. Rewriting them to make it more expression like does
nothing to change that.

------
naz
Just use whatever seems clearer

~~~
akkartik
Yep. Use else when the two branches do symmetrical amounts of work. Don't use
else if one is an early return.

If you find this discussion interesting you're probably stuck with codebases
with overly long functions. My commiserations.

------
redcap
I think the main problem is the lack of braces means you have to rely on white
space to figure out what the hell is going on.

That's the main reason why I religiously put open and close braces on even the
smallest if/else blocks as it dramatically improves the readability of the
code.

If the mozilla code style specified that you have to use braces no matter what
then they wouldn't be having this problem.

Of course, I'm probably arguing with hackers who prefer to use constructs like
'return (a > b ? a : b)' rather than write readable code.

This is coming from someone who likes to put spaces after and before
parentheses so it makes it easier to figure out what's going on.

e.g. if ( ( y > x ) || ( x < 10 ) ) - this makes things easier to read (for
me) when you start to get a hell of a lot of nesting going.

~~~
philwelch
The ternary operator is perfectly readable if you spend even the slightest
amount of time getting used to it.

I like spacing my parens too, but what you wrote isn't as readable to me as:

    
    
      ( (y > x) || (x < 10) )
    

Spacing _inside_ your terminal pair of parens only makes your atomic
expressions harder to read.

I also like multiline expressions:

    
    
      if (  (x == 10) ||
            (y == 10) ||
            (x > y) )
      {
        .....
      }

~~~
anamax
Why do you put the operators for multiline expressions at the end of the
preceeding line instead of at the beginning of the next line?

With statements, the first token on the line tells you what it's doing and the
indentation tells you about its relationship to statement on the previous
line. Why not do something similar for multi-line expressions?

~~~
philwelch
I like aligning the atomic conditional tests I'm or'ing together, and that's
the most space-efficient way to do it. I guess I could indent the first line
more and put the or operators on the left, though.

------
ori_b
And here we have a classical bikeshedding article.

This sort of thing really doesn't matter much one way or another. Do what the
rest of the codebase is doing, and move on with your life. If you're writing
your own code, do what you feel like doing.

------
wglb
I disagree. The rule works for me.

I now find myself using 'cond' almost exclusively over 'if'.

And there is a little misunderstanding propagated: "Even in a language like
C/C++ you can do something approaching functional programming by avoiding
statements". I don't think so.

