http://qs321.pair.com?node_id=11124115


in reply to Re^6: What's the right way to write a method which returns one line at a time from a file?
in thread What's the right way to write a method which returns one line at a time from a file?

You're almost in my lane :)

The key for my claim is that the return/exit/die/croak is the last unconditional statement in the if block. I might have been clearer on that.


Enjoy, Have FUN! H.Merijn
  • Comment on Re^7: What's the right way to write a method which returns one line at a time from a file?
  • Select or Download Code

Replies are listed 'Best First'.
Re^8: What's the right way to write a method which returns one line at a time from a file?
by jcb (Parson) on Nov 24, 2020 at 23:57 UTC

    Your rule would forbid:

    if (...) { return A } elsif (...) { return B } elsif (...) { return C } else { die "unmatched case" }

    This is why I say it is ridiculous, because I see that construct as a perfectly legitimate way to handle returning different values in different cases. The final die (or a final return undef) is indented along with all of the other cases. Omitting the else would place it one level out. Note that an if-elsif chain like this obviously can have no code following it, but the else here simply highlights that one of these will be executed. Also note that I tend to omit the semicolon after return/last/next/die/etc. in Perl because there should not be another statement after any of those and omitting the semicolon promotes such dead code to a syntax error.

      As others already stated, your code is confusing and yes, my rule would forbid that.

      Your code has no more value than any of these (all clearer):

      if (EXPR1) { return A }; if (EXPR2) { return B }; if (EXPR3) { return C }; die "unmatched case"; EXPR1 and return A; EXPR2 and return B; EXPR3 and return C; die "unmatched case"; return A if EXPR1; return B if EXPR2; return C if EXPR3; die "unmatched case";

      For short expressions, my personal preference is the middle one. The first is the best choice if it is likely that the blocks can have statements before the return.

      I personally do not like statement modifiers, so I would not choose the third option, but it is still by far better than your example.

      Opinions differ though. TIMTOWTDI. But you still have shown no reason why my ruling would be rediculous. You only showed an example that strenghtens my opinion on it.


      Enjoy, Have FUN! H.Merijn

        Fair enough; that example was poorly formatted for that exact code. That approach is far more useful when there is more than just a return in each branch and the program must choose one of several relatively expensive calculations. The formatting I used is better when the expressions are long enough that if (...) { return A } will not fit on one line, but I would collect the conditions into a "table" if they fit. Like:

        if (EXPR1) { return A } elsif (EXPR2) { return B } elsif (EXPR3) { return C } else { die "unmatched case" }

        That said, while I see the point that else can be unnecessary, I still consider forbidding it to be absurd. I also expect that a future optimizing compiler could make use of an if-elsif chain more easily, although rewriting multiple if (...) { ...; return } into if-elsif is only slightly more complex.

      Somewhat tangential, but a less messy, more readable and preferable (IMHO) version of this is:

      return COND_A ? A : COND_B ? B : COND_C ? C : COND_D ? () : # returns undef or empty list per context die "unmatched case" ;


      Give a man a fish:  <%-{-{-{-<

        Yes, I agree. I especially like that there is only one return statement. In contrast, using multiple return statements violates the principle of DRY.

        Related items from Conway's Perl Best Practices, Chapter 6 (Control Structures):

        • Avoid cascading an if
        • Use table look-up in preference to cascaded equality tests
        • When producing a value, use tabular ternaries

        Conway recommends formatting tabular ternaries with the colon at the front, for example:

        # When their name is... Address them as... my $salute = $name eq $EMPTY_STR ? 'Customer' : $name =~ m/(.*), \s+ Ph[.]?D \z /xms ? "Dr $1" : $name ;
        because, if you squint, it looks like a lookup table, thus converting the notoriously impenetrable ternary syntax into a familiar and easy to understand lookup table.

        Update: Fixed typo in Conway's example my $salute statement above (removed extra ?). Thanks AnomalousMonk.

      I see that construct as a perfectly legitimate way to handle returning different values in different cases.

      It is legitimate but all those unnecessary elsifs and elses spread confusion. Why are they there if they serve no purpose? TIMTOWTDI but I prefer the clarity of

      return A if FOO; return B if BAR; return C if BAZ; die "unmatched case";

      🦛