Perl syntax question: Boolean result?

Dieser Post wurde aus meiner alten WordPress-Installation importiert. Sollte es Darstellungsprobleme, falsche Links oder fehlende Bilder geben, bitte einfach hier einen Kommentar hinterlassen. Danke.

A new task at work made me hunting warnings, mostly "Use of uninitialized value" messages. One simple line creating such noise was
my $country_href = $countries->{$setup{countrycode}} || 0;
It turned out, that  $setup{countrycode} wasn't guaranteed to be defined and Perl complained.

My fix was quick and simple:

my $country_href = ($setup{countrycode} and $countries->{$setup{countrycode}}) || 0;
Assuming that the ISO committee never assigns "00" as country code :-)

This one-line-commit started a little discussion (and I appreciate source code discussions) about the ( ) result. I know think, that ("true" and 3) evaluates 3 only of "true" is true and returns the value of the last element. This makes sense, since the whole and can't be true unless the last item is also true when being used as a condition.

I try to avoid adding more and more code lines unless it improves readability or has some other advantage, so adding a multi-line if-then-else-monster wasn't an option.

What do you think? How would you remove that warning? (Please don't tell me to remove "use warnings;" from the file :-) )


7 Kommentare. Schreib was dazu

  1. anon

    Use a defined-or clause in the hash ref (perl 5.10+ only) and take advantage of autovivification

    my $country_href = $countries->{ $setup{countrycode} // 0 };

  2. anonymous

    AA, ZZ, all starting with X and some starting with Q are reserved. To comply with the ISO standard, use any of those instead of 0.

  3. I would expect to see that written as

    my $country_href = $setup{countrycode} && $countries->{$setup{countrycode}} || 0;

    to avoid having to use the parentheses. Using the short-circuit logic of && and || in this way is a pretty common idiom; however, it is often better to find out how the undef value got to this point than to just silence the warning. Often an undef value is a sign of either a programming error or a design flaw.

  4. A. Guest

    my $country_href = (
    $setup{countrycode} and exists $countries->{$setup{countrycode}}
    ) ? $countries->{$setup{countrycode}} : 0;

    Makes it easy to see what gets assigned to $country_href, works with '00' as country code.

  5. Ricky Morse

    Hi! I would probably do something like:

    my $country_href = exists($setup{countrycode}) ? $countries->{$setup{countrycode}} : 0;

    But I don't think there's anything wrong with using the "and" format. I would, however, make the test exists (or, possibly, defined) instead of just testing the boolean value.

  6. Alexander Hartmaier (abraxxa)

    put it into a no warnings 'uninitialized'; block if you don't care about it being undef.

  7. Richard Huxton

    If you are running anything recent (perl 5.10+)

    my $country_href = $countries->{$setup{countrycode}} // 0;

Schreib was dazu

Die folgenden HTML-Tags sind erlaubt:<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>