in reply to Re^2: return if defined
in thread return if defined

I view your sample code the very thing wrong with the "single return" principle. My dogma is: return as early as you can if it avoids extra indentation.

(One of the usual offenders is a lengthy if {} block with the main logic, coupled with a short else {} block whose only purpose is to return some error value. Just reverse the blocks' order and the main logic no longer needs an extra indent level!)

Replies are listed 'Best First'.
Re^4: return if defined
by Anonymous Monk on Dec 20, 2012 at 13:39 UTC

    Wow, I have a split personality today.

    I agree that error handling is the real bugbear of single-return. Special additional logic and/or an extra state variable are often required to make it work. It makes code less clear and sometimes even more error-prone. "Break out now" makes the most logical sense in a failure case.

    But I see this example as different: there is one kind of result that could be created in one of two different ways. The if statement doesn't add any complexity to the code--you have to check for definedness somehow. Nor does it hurt clarity. Why is indenting so bad?

    This is not to say that I object to your preferred solution. I think that's fine, too.

      There's nothing really wrong with indenting apart from making your code narrower. (This split personality adheres to the 80-character-per-line rule.) Excessive indentation, however, is a code smell to me. I usually accept about four levels: one for the function, two for a nested loop, and the last one for a potential if block inside the loop. Anything more and I try to break it into smaller functions. (And I just habitually minimise indentation as I feel it makes it easier to follow the overall logic.)

        There's an easy solution to that: ;-)

        package Foo { sub foo { ...; while (my $row = $st->fetchrow_array) { ...; for my $value (split /,/ $row->[3]) { if ($value == 0) { ...; while (not $finished) { ...; if ($happy) { $finished++; if (@complaints) { while (defined(my $c = shift @complaints)) { ...; } } } } ...; } } } ...; } }
        perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'