in reply to Re: A question about method return values and error checking
in thread A question about method return values and error checking

A counter example to consider: let's say the code in question was:
printf <<EOF, $os->name( long => 1 ), $os->version; Operating System: %s Version : %s EOF
In order for the output to make sense, you would actually want a placeholder in the list for the name. In the general case, invoking $os->name in a list context doesn't really make much sense unless you really have an explicit list of values.

#11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Replies are listed 'Best First'.
Re^3: A question about method return values and error checking
by dsheroh (Monsignor) on Nov 05, 2015 at 07:41 UTC
    That's resolved trivially:
    printf <<EOF, $os->name( long => 1 ) // 'unknown OS', $os->version // +'unknown version'; Operating System: %s Version : %s EOF
    If you return empty strings on failure instead of undef, then you'd need to use || instead of //, which could cause issues if 0 is a potential return value. (Not likely in the specific example of OS name/version, but relatively common in the general case.) So, personally, I'd chalk that up as another point in undef's favor.
      The discussion was about concerns that return undef; in list context returns a list that is one element long, and thus true. In contrast, a bare return; in list context returns a zero-length result. This is a point that is lost on many acolytes. return undef; might bite you if you naively did something like:
      my @names = $os->name( long => 1 ) or next; # No names
      On the other hand, of you did
      my @names = map $_->name( long => 1 ), @oses;
      you would end up with lists of different lengths with the bare return;. Your solution puts the list elements back in scalar context, and thus avoids the actual question.

      Update: I remembered where it really bites people:

      my %hash = (name => $os->name( long => 1 ), version => $os->version, );
      where the mismatch has now resulted in a transposition of keys and values.

      #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

        my @names = $os->name( long => 1 ) or next;

        That seems more like a strawman to me. I just haven't run into code where people do list assignments in boolean context when using a sub that just returns a single scalar. It is an unnatural construct.

        While using a scalar-returning sub as part of some list is done very often.

        So subs that never return more than 1 scalar should never use return;. Subs that clearly return a list should avoid using return undef; to indicate failure.

        - tye        

        Yes, agreed. I misunderstood your earlier reply to me as having been concerned about the lack of default placeholder strings on failure rather than with what it does to the structure of lists with positional dependencies (such as hashes and printf arguments).

        Fortunately, the solution presented in my previous reply resolves both of these issues.

      The OP had an oops moment when some (poorly documented?) method was mis-used. A blank return; could make that oops even worse, in a list context. Thence the recommendation to go with return undef.