Live data from Hacker News

Avoid Else, Return Early (2013)

blog.timoxley.com

431–440 of 601 posts

Re: Avoid Else, Return Early (2013)

#431
While I think the advice in this post is pretty sound (guard clauses are a great alternative to bailing out of a function in various places, because you can see the conditions up front and not as what is essentially an afterthought), I do take issue with the language we tend to use when sharing advice.

The advice we give is often prescriptive or absolute, in that you have to avoid doing something, or you should never do something, or there is a best practice. More often than not it strips out the nuance, as if the new position has somehow managed to resolve all of the issues that cause the year--even decade--long debates in the first place, and it is far more often the case that the choice is more than preferential.

And what makes it bizarre is evidenced in the article itself: the original, prescriptive position is neutered in a follow-up edit that claims to take the position in balance because it won't make sense in every situation.

The top comment in this thread talks about the evolution of a programmer; surely one of the greater evolutions of your career in the field is to understand that all of this advice is purely dependent on context and an all-or-nothing approach to rule making isn't going to cut it; in fact it will likely make things worse when aspiring programmers take it as gospel and start trying to shoehorn these best practices into whatever code they can, adding all kinds of linters and such to enforce the rules in all cases and prioritizing style over implementation in code reviews. Code must fit in 80 characters in a line; it must omit semi-colons if it's JS; it must use 2 spaces for indentation; it must be extracted into a method if it has more than 5 lines...no matter what.

As an alternative, I instead propose that you think of good or better practices, also known as reasonable guidelines, and if you're going to build a style guide around them at least try to provide some alternatives should the preferred solution not fit the problem the programmer is currently facing. Treat it as an opportunity for mentoring and not just an instruction manual.

Re: Avoid Else, Return Early (2013)

#433
post #238

In Common Lisp the syntax for early return is so ugly (```(return-from function-name result)```) that I use it very rarely. In general, it seems that in the languages that use implicit return (Lisps, Haskell, Rust?) having an early return is discouraged by design.

In Lisp other structures come into play that effectively give you early return in various situations, like for example cond.

  (cond
    (early-return-condition early-value)
    (second-early-condition early-value2)
    ...
    (t final-else-value))
A cond as the last (or only) form of a body is basically an N-way switch toward multiple exit points, the ones appearing first being earlier.

In TXR Lisp I made block have dynamic scope, not only dynamic binding. You can do this:

   (defun helper ()
     (return-from master 42))

   (defun master ()
     (helper))
I.e. early return from nested helper functions, without a lot of added ceremony.

Speaking of this dialect, here is a function from its C internals, exhibiting a preference for an early return over else:

  val flatten(val list)
  {
    if (list == nil)
      return nil;

    if (atom(list))
      return cons(list, nil);
              
    return mappend(func_n1(flatten), list);                              
  }                                                                                                   
If this were in the Lisp dialect instead of C, the same author would write it like this:

  (defun flatten (list)
    (cond
      ((null list) nil)
      ((atom list) (list list))
      (t [mappend flatten list])))
and certainly not like this:

  (defun flatten (list)
    (when (null list)
      (return-from flatten nil))
    (when (atom list)
      (return-from flatten (list list))
    [mappend flatten list])
Even if the implicit block around a function body were the anonymous block, so that (return (list list)) could be used, this would still be eschewed as unidiomatic Lisp.

Re: Avoid Else, Return Early (2013)

#434
post #166

Earlier quoted context omitted.

That's fine -- the Python folks have their own share of religious wars (starting with: tabs, or spaces?) :-)

Do they? All the Python folks I've ever seen express an opinion on style have said "follow PEP 8". Unsurprisingly, PEP 8 does have a rule for tabs vs. spaces: https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces (spaces, of course)

The PEP8 myth is quite funny. Almost all people I've met who were repeating "follow the pep8" like a mantra, have never read it. The main idea behind pep8 is: be consistent... however even the python library is not consistent. And it looks like no one cares. There was a great moment to make it nice and consistent - creating the python3, where many incompatible changes were introduced. Instead, the mess is like it was, and people repeat the mantra "follow pep8".

Before you say that I'm crazy... please, go and read pep8.

Re: Avoid Else, Return Early (2013)

#435
post #354

Earlier quoted context omitted.

I don't think throwing void at people is generally going to make anything clearer.

why

I've never seen syntax like 'if (err) return void handleError(err)' before. If I saw that in JS I'd have to look up what it meant.

Re: Avoid Else, Return Early (2013)

#436
If you are working in C (not C++ with RAII), return early is a huge headache and maintenance hassle. Basically you want to free any loose buffers on any exit path out of the function, and if you only have one place out of the function, you only have one place to put it.

Or, as I think of it sometimes, if you have N buffers and M early exits, you need O(NM) free statements. When the code changes over time with more exit paths, you need to change that many places. So best to make M=1 for greatest sanity.

A language that does this for you more automatically (either RAII, or GC) then sure, early exit away. Although, one further point I do like about the more explicit C style is you end up writing code that looks very similar in the failure path and success path, which makes you prepared for when things inevitably fail...

Re: Avoid Else, Return Early (2013)

#437

Earlier quoted context omitted.

Totally disagree with you.... it's funny though that I read LOC as "level of complexity" not "lines of code". I've been writing code for 30 years and I think it's jarring when the braces are on the next line, so much easier for me to parse that when it's on the same line. But everyone is entitled to their own opinion.

python fans are going like "what are braces?"

Tell them braces are visual indicators of blocks of logic, enabling reasoning more easily on a multi-statement level.

Re: Avoid Else, Return Early (2013)

#438
post #95

Earlier quoted context omitted.

> Same way you get joy deleting large swaths of code. This is the true sign of a programmer's transcendence. Specifically the irrational joy of seeing net negative LOC diffs. It's not about how much you can add. It's about how much you can remove without sacrificing correctness, functionality, and readability.

I always tell my team that deleted code is the best code. Obviously less code is often more maintainable but there is also the element of being willing to throw away stuff you did earlier and not being attached to it.

I remember teaching a guy about YAGNI - You Ain't Gonna Need It.

He would write helper functions that he thought would be useful before writing actual code and often ended up wasting time. Half the functions he wrote, he never actually used, but he'd still spend time writing them and unit tests for them.

Re: Avoid Else, Return Early (2013)

#439
post #431

While I think the advice in this post is pretty sound (guard clauses are a great alternative to bailing out of a function in various places, because you can see the conditions up front and not as what is essentially an afterthought), I do take issue with the language we tend to use when sharing advice. The advice we give is often prescriptive or absolute, in that you have to avoid doing something, or you should never…

[deleted]

Re: Avoid Else, Return Early (2013)

#440
post #431

While I think the advice in this post is pretty sound (guard clauses are a great alternative to bailing out of a function in various places, because you can see the conditions up front and not as what is essentially an afterthought), I do take issue with the language we tend to use when sharing advice. The advice we give is often prescriptive or absolute, in that you have to avoid doing something, or you should never…

Most of those rules suggested are too ridged can be accomplished by formatters hooked into an editor's save function or version control commit. I don't want my developers spending any more time on whitespace. Anything not solved by an automated process should certainly be on a case by case basis. If half a file has semi colon endings it's reasonable to request it be uniform for that file.

The benefit to automated formatting is the style configuration can be swapped. if I HAVE to see altman brackets my editor can cook that format while my version control can hook whatever format the project requires.

Post reply on HN