nysus has asked for the wisdom of the Perl Monks concerning the following question:

I've come across a minor annoyance demonstrated by this code snippet:

my ($a, $b, $c, $d) = 'abcd' =~ /(w)(x)(y)(z)/; print "$a $b $c $d";

Running this results in a bunch of "Use of uninitialized value" errors. To appease Perl, I am forced to test each variable to see if it's undefined and set each variable to an empty string if it is.

Are there any suggestions out there for an idiom for avoiding this annoyance without turning the warnings off?

$PM = "Perl Monk's";
$MCF = "Most Clueless Friar Abbot Bishop Pontiff Deacon";
$nysus = $PM . $MCF;
Click here if you love Perl Monks

  • Comment on Idiom for setting variables to empty string if capture is undefined?
  • Download Code

Replies are listed 'Best First'.
Re: Idiom for setting variables to empty string if capture is undefined?
by BrowserUk (Patriarch) on Dec 06, 2015 at 07:43 UTC
    an idiom for avoiding this annoyance without turning the warnings off?

    If you know the warnings are a possibility for particular statements, why not disable the warnings for those particular statements?:

    my ($a, $b, $c, $d) = 'abcd' =~ /(w)(x)(y)(z)/; { no warnings 'uninitialized'; print "$a $b $c $d"; }

    Or:

    printf "%s %s %s %s\n", $a//'', $b//'', $c//'', $d//'';

    Or, ensure they get some value:

    my ($a, $b, $c, $d) = ( 'abcd' =~ /(w)(x)(y)(z)/, '','','','' );

    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Idiom for setting variables to empty string if capture is undefined?
by choroba (Cardinal) on Dec 06, 2015 at 07:47 UTC
    Before anything else, let's change the variable names. $a and $b are reserved for sort, lexicalizing them could lead to strange behaviour.

    There are several ways how to prevent the warnings. The most common one is to test whether there was a match:

    if (my ($x, $y) = 'ab' =~ /(x)(y)/) { print "$x$y\n"; }

    Another possibility it to use the convenient defined-or operator (Perl 5.10+ needed):

    my ($x, $y) = 'ab' =~ /(x)(y)/; print $x // q(), $y // q(), "\n";
    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
      "...$a and $b are reserved for sort..."

      Sure, they are.

      "Everything You Always Wanted to Know About $a and $b (*But Were Afraid to Ask)" (freely adapted from Woody Allen)

      But the OP doesn't sort. And what about localizing them in a block if he really wants/needs this variable names for some unknown/weird reasons?

      Regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

Re: Idiom for setting variables to empty string if capture is undefined?
by Corion (Patriarch) on Dec 06, 2015 at 08:32 UTC

    My personal choice for "strings that can be present or empty" instead of "strings that can be present or undefined" is to allow for that in the regular expression as well (at the cost of some backtracking):

    my ($a, $b, $c, $d) = 'abcd' =~ /(w|)(x|)(y|)(z|)/; print "$a $b $c $d";

    This approach will need some additional care if the matches for w and x could overlap for example. Also, some anchoring might be needed to make certain that something is matched at all, as that regular expression can easily "match" by matching an empty string at the beginning of the match target.

Re: Idiom for setting variables to empty string if capture is undefined? (map defined $_ ? $_ : '' , m//
by Anonymous Monk on Dec 06, 2015 at 09:06 UTC
    use strict; use warnings; $_='a'; my( $a, $b, $c ) = map defined $_ ? $_ : '' , m/(.?)(.?)(.?)/; print "'$a''$b''$c'\n"; __END__ 'a'''''
Re: Idiom for setting variables to empty string if capture is undefined?
by soonix (Chancellor) on Dec 06, 2015 at 17:06 UTC

    Similiar to what choroba said, I would change the variable names, too. But $x, $y, $z is not significantly better.

    You could name them $match1, $match2, $match3, … - but then, why not simply
    my @matches = 'abcd' =~ /(w)(x)(y)(z)/; print join ' ', @matches;
Re: Idiom for setting variables to empty string if capture is undefined?
by Anonymous Monk on Dec 06, 2015 at 18:44 UTC
    $_ //='' for my ($c, $d, $e, $f) = 'abcd' =~ /(w)(x)(y)(z)/; print $c, $d, $e, $f;

    How's this for an idiom ?