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

Hello, I have a 355 line code that takes about 3 hours to run. I find errors like "Use of uninitialized value in subroutine entry at meth_analysis.pl line 311" I have 4 different arrays on this line which could have been uninitialized. How can I set perl to change this warning to something like "Use of uninitialized value $hash{key1}{key2} in subroutine entry at meth_analysis.pl line 311" in other words, how can I get the uninitialized warnings to tell me which value is uninitialized? To compensate for the vague warning, I have littered my code with "if(!defined($var))" but I would prefer a better solution than this. thanks, -DEC

Replies are listed 'Best First'.
Re: change unintialized warning
by LanX (Saint) on Mar 02, 2015 at 13:37 UTC
    Pragmatic solution? :)

    Split the logic in line 311 into multiple lines (i.e. different ; separated statements!) for debugging.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)

    PS: Je suis Charlie!

Re: change unintialized warning
by Anonymous Monk on Mar 02, 2015 at 13:57 UTC

    I'm not sure if Perl's warning message can be customized this way. LanX's suggestion would probably help in that regard. See perldiag (emphasis mine):

    Use of uninitialized value%s

    (W uninitialized) An undefined value was used as if it were already defined. It was interpreted as a "" or a 0, but maybe it was a mistake. To suppress this warning assign a defined value to your variables.

    To help you figure out what was undefined, perl will try to tell you the name of the variable (if any) that was undefined. In some cases it cannot do this, so it also tells you what operation you used the undefined value in. Note, however, that perl optimizes your program and the operation displayed in the warning may not necessarily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer to the concatenation (.) operator, even though there is no . in your program.

    Does your code treat undefs like the empty string or 0, or do you treat undefs differently? If you treat them differently, you'll have to put logic at all the appropriate places to handle them. If not, then one solution is to change all undefs to the empty string or 0 at the point where your data structure is populated, e.g. $hash{$foo}{$bar} = $value//"";, or later on, e.g. $_//=0 for @values;. Or you could say no warnings 'uninitialized';, but then you might miss mistakes in some places.

Re: change unintialized warning
by marinersk (Priest) on Mar 02, 2015 at 15:13 UTC

    To build on LanX's note:

         $test1 = $test2 = $test3 = 6;

    Is better written as

         use strict;

         my $test1 = 6;
         my $test2 = 6;
         my $test3 = 6;

    Or even better as

         use strict;

         my $DEFAULT_TEST_VALUE = 6;

         my $test1 = $DEFAULT_TEST_VALUE;
         my $test2 = $DEFAULT_TEST_VALUE;
         my $test3 = $DEFAULT_TEST_VALUE;

    And clever you -- you just stumbled onto one of the many, many, many reasons why.

    That said, the if(!defined($var)) approach is about as graceful as it gets, although you might be able to make use of the new-fangled // operation to save some typing.