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

I have a piece of code that does stuff randomly. Using rand (which is sufficiently random for my purposes). So that's on purpose. However, I want to be able to test certain scenarios specifically (code coverage, sorta). So I figured that since all random generation goes through a single _random function, I could just easily put a debug-hack in there that would allow me to specify the random numbers. However, I seem to get some wierd behaviour in the debug code - it's not critical, but I'm curious as to how to quash it.

The problem is given by the code below. I'm sure I could get this simpler, but I was just happy to reproduce it at all (I fought with it for about 5 minutes until I realised that, duh, the warning would only come up if I turned on warnings...).

The warning is: "Use of uninitialized value in list assignment at ./a.pl line 13."

use strict; use warnings; my $foo = '1Z1'; $ENV{Z1Z1} = '3,2,1'; for (1..5) { my $x = '?'; if ($ENV{'Z' . uc $foo}) { ($x, $ENV{'Z' . uc $foo}) = split /,/, $ENV{'Z' . uc $foo}, 2; } print $x, $/; }

Output:

3 2 Use of uninitialized value in list assignment at ./a.pl line 13. 1 ? ?

Expected/desired output: everything except the warning.

Ideally, this would be done without "no warnings" inside the assignment. If that's not possible, I'll just stick in that pragma and be done with it - I just don't like avoiding warnings or strict unless I know that it's the only way to do what I want to do, and I'm not that confident here yet.

Thanks,

Replies are listed 'Best First'.
Re: Uninitialised value in list assignment
by davidrw (Prior) on Jun 26, 2005 at 22:09 UTC
    Well, it's warning cause there's an undef on the third split :)
    ($x, $ENV{Z1Z1}) = ( '3', '2,1' ); # first time ($x, $ENV{Z1Z1}) = ( '2', '1' ); # second time ($x, $ENV{Z1Z1}) = ( '1', undef ); # third time
    To avoid it, you can explicitly get and check the split() results:
    my @arr = split /,/, $ENV{'Z' . uc $foo}, 2; $x = shift @arr; $ENV{'Z' . uc $foo} = scalar @arr ? $arr[0] : ''; # set to empty s +tring if nothing available

      Yes, but I guess what has me confused is why: perl -we '$x=1;$y=1;($x,$y)=("1",undef)' doesn't give any warning, while: perl -we '$x=1;($x,$ENV{y})=("1",undef)' does. Upon which I think I just found my solution... just use a temp variable for the two, and the warning goes away... although it seems strange that this warning is only for the list case, and that it only comes up when %ENV is being assigned to. If I use %E rather than %ENV, the error doesn't come up, either. Wierd.

      Update: Duh, it's because I'm assigning undef to an environment variable Sigh. That warning was a bit too wierd for me to figure out. Chalk that one up to experience - I now have some more. Sorry for wasting your time - hopefully you can learn from this public "D'oh!" moment.

        Yup; normally assignment doesn't trigger any warnings, but if there's magic attached to the assignee, it may. Here's another example:
        $ perl -we'$|="abc"' Argument "abc" isn't numeric in scalar assignment at -e line 1.
Re: Uninitialised value in list assignment
by tlm (Prior) on Jun 26, 2005 at 22:04 UTC

    The problem is that when $ENV{'Z' . uc $foo} contains only the string "1", then

    split /,/, $ENV{'Z' . uc $foo}, 2
    returns a list of 2 elements (due to the last argument to split) whose last element must necessarily be undefined. The assignment of this undefined value to $ENV{'Z' . uc $foo} triggers the warning.

    the lowliest monk

Re: Uninitialised value in list assignment
by xdg (Monsignor) on Jun 27, 2005 at 03:43 UTC

    You might consider checking out Test::MockRandom. I wrote it for just this kind of thing. There's also an article on it in the summer edition of The Perl Review.

    -xdg

    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Re: Uninitialised value in list assignment
by demerphq (Chancellor) on Jun 27, 2005 at 10:51 UTC

    Contrary to the assertions made by some of the other posters so far, split does NOT return the number of arguments specified by the third argument if there are less items than is specified, NOR does a warning get raised when you assign undef to a variable using list assignment, nor is it an error to do so with mismatched elements on either side. In fact this warning only has the remotest connection to the split or list assignment. The problem is that %ENV is a tied variable. Try the code with a lexically declared %ENV and the warnings go away.

    ---
    $world=~s/war/peace/g