in reply to Re: How to determine if an array contains an undef value?
in thread How to determine if an array contains an undef value?

Hello Anonymous Monk,

Thank you for your input, this is an interesting observation.

Seeking for Perl wisdom...on the process of learning...not there...yet!

Replies are listed 'Best First'.
Re^3: How to determine if an array contains an undef value?
by locked_user sundialsvc4 (Abbot) on Jan 05, 2015 at 13:46 UTC

    That observation might be extended to say ... “be careful of simple-tests for ‘falseness,’ if there are several different kinds of ‘falseness’ that you actually need to distinguish.”   Explicitly test for things using exists(), defined(), and so on.   Actually, I customarily test explicitly for every explicit that I expect to see, and cause the program to die() if it falls through all of the cases.   Tests for the “falseness” of the return-value are used in my code only when the value is 1 or 0.   The program catches a lot of its own bugs this way ... especially a concern in a typeless language like Perl.

      Tests for the “falseness” of the return-value are used in my code only when the value is 1 or 0.
      I more or less agree with the rest of what you are saying, but I do not agree with that. It is perfectly legitimate, Perlish and idiomatic to evaluate an array in scalar/boolean context to figure out if it is empty. The scalar return value may be 0 (the array is empty) or 1, 2, 3, ..., any positive integer other than 0 (the array is not empty). For example:
      while (@array) { my $val = shift @array; # do something with $val }
      or possibly:
      while (my $val = shift @array) { # ... }
      or:
      if (length $string) { # ... }
      (but not if ($string), because that might not give the expected result with the string "0"). Or you could have a sub return undef (false) if it did not succeed, or a hash or array reference (something that is always true), or even a simple array or hash, if it did succeed.

      Similarly, if you open a file with this idiomatic syntax:

      open my $fh, "<", $file or die "failed to open $file $!";
      you're not testing for 0 or 1, and yet it works perfectly and is considered to be a best practice.

      Of course, you've gotta know what you're doing and should probably try not to be too clever. I once got bitten by something like this:

      $error_count++ and next if some_condition();
      which did not work correctly the first time through the loop, because $error_count was 0 (or undef, whatever it was, I don't remember, it happened some years ago). While:
      ++$error_count and next if some_condition();
      would have worked fine, I was probably trying at the time to be a little bit too clever (and too concise).

      Limiting boolean tests to only 0 and 1 values is taking off a lot of Perl's expressive power.

      Update: crossed out one example after the comment below from Anonymous Monk.

        If $val is undef the loop ends
        $ perl -MO=Deparse -le " while (my $val = shift @array) { print $val } + " BEGIN { $/ = "\n"; $\ = "\n"; } while (my $val = shift @array) { do { print $val }; } -e syntax OK

        $error_count++ and next if some_condition();

        Comma to the rescue

        $error_count++, next if some_condition();