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

Could one of the esteemed monks who delves into arcane behaviour please assist me.

I have a snippet of code:

print STDERR "$rec->[IMP_WG] $rec->[CSC_HAN]\n"; if ( defined( $rec->[IMP_WG] ) && $rec->[IMP_WG] ne '' && defined( $rec->[CSC_HAN] ) && $rec->[CSC_HAN] eq '1' ) { print "$rec->[CLASSIF] $rec->[IMP_WG] $rec->[SRV_PLT]\n"; }

That produces (in part) the following output (greenfox you can look away now):

CSC.MIDRANGE.SERVER.SUPPORT 1 CSC.MIDRANGE.SERVER.SUPPORT 1 CSC.MIDRANGE.SERVER.SUPPORT 1 Use of uninitialized value at stats2 line 190. CSC.NETWORK.ENG 1 Use of uninitialized value at stats2 line 190. 0 CSC.MIDRANGE.SERVER.SUPPORT 1 Use of uninitialized value at stats2 line 190. 0 CSC.NT.SERVER.SUPPORT 1 Use of uninitialized value at stats2 line 190.

Line 190 is the 'if' statement in the listed code.

The input data is the result of a split operation and it is possible that the indexes IMP_WG and CSC_HAN could contain undef values.

This is perl, version 5.005_03 built for sun4-solaris.

use strict; and -w are in use.

Any suggestions about what I am missing?

20040108 Edit by jeffa: Changed title from 'I dont understand why Perl is complaining.'

Replies are listed 'Best First'.
Re: split, Use of uninitialized value
by pg (Canon) on Jan 07, 2004 at 03:56 UTC

    Here is your code:

    print STDERR "$rec->[IMP_WG] $rec->[CSC_HAN]\n"; if ( defined( $rec->[IMP_WG] ) && $rec->[IMP_WG] ne '' && defined( $rec->[CSC_HAN] ) && $rec->[CSC_HAN] eq '1' ) { print "$rec->[CLASSIF] $rec->[IMP_WG] $rec->[SRV_PLT]\n"; }

    The print statement in the first line will be executed regardlessly. If in deed, $rec->[IMP_WG] and/or $rec->[CSC_HAN] are/is uninitialized, the warning you saw should be issued. To avoid this, simply test the values before you print, as you did in your second line.

Re: split, Use of uninitialized value
by Roger (Parson) on Jan 07, 2004 at 03:26 UTC
    I wrote the following test and ran it under version 5.005_03 of perl. It showed that the warning was on the print line before the if. Printing undef will result in the warning.

    #!/usr/bin/perl -w use strict; use Data::Dumper; use constant index1 => 0; use constant index2 => 1; my $rec = [ undef, 1 ]; print Dumper($rec); # inspect before if print "$rec->[index1] $rec->[index2]\n"; # warnings here (line 11) if ( defined $rec->[index1] && $rec->[index1] ne '' && defined $rec->[index1] && $rec->[index1] eq '1' ) { print "OK\n"; } else { print "Not OK\n"; } print Dumper($rec); # and check again after if
    I don't think your if test will 'autovivify' anything because of the short circuit behaviour of the && operator. has anything to do with autovivification at all, given that the $rec has a fixed number of records. See pg's comments above and below.

    $VAR1 = [ undef, 1 ]; Use of uninitialized value at ./p09.pl line 11. 1 Not OK $VAR1 = [ undef, 1 ];
      "I don't think your if test will autovivify anything because of the short circuit behaviour of the && operator."

      It is true there is no autovivification, but it certainly has nothing to do with short circuit. If it should cause any autovivification, the first defined() call already triggered it, certainly no need for that 'ne' after the && to carry it out.

      What autovivification says is that, read/test a non-exist element of a container, creates the ancestors of that node automatically. This is obviously not what is going on here.

      Some definitions ...

      use constant IMP_WG => 18; use constant CSC_HAN => 19;

      And a dumped record with some data blanked out.

      CSC.MIDRANGE.SERVER.SUPPORT 1 $VAR1 = [ 618, 'xxxxxxxxxx', '3-Moderate', 'Normal', 'Closed', 'xxxxxxxxxx', 'xxxxxxxxxx', 'Approved', 'Approved', '05/12/03 10:00', '02/12/03 09:45', '3.00', 'Successful', '12/12/03 09:53', '05/12/03 13:00', '05/12/03 09:52', 'Midrange', 'Production', 'CSC.MIDRANGE.SERVER.SUPPORT', 1 ]; Use of uninitialized value at stats2 line 192.

      As far as I can see in all cases the data I am testing does exist. I previously had the final test as $rec->[CSC_HAN] == 1 but that was one of the first things that I changed.

      I cant see any scope for autovivification either ... the only possibility would be $rec but then the print statement should be throwing the uninitialised value errors.

      If it matters (and it probably does with something this weird) $rec is a local copy of a pointer stored in a hash and obtained like so:

      my $rec = $change_recs{$key};
        What's SRV_PLT defined as?

        I defined a new out of range index3 in the following example -
        #!/usr/bin/perl -w #use strict; use Data::Dumper; use constant index1 => 18; use constant index2 => 19; use constant index3 => 20; my $rec = [ 618, 'xxxxxxxxxx', '3-Moderate', 'Normal', 'Closed', 'xxxxxxxxxx', 'xxxxxxxxxx', 'Approved', 'Approved', '05/12/03 10:00', '02/12/03 09:45', '3.00', 'Successful', '12/12/03 09:53', '05/12/03 13:00', '05/12/03 09:52', 'Midrange', 'Production', 'CSC.MIDRANGE.SERVER.SUPPORT', 1 ]; # @$rec = map { defined($_) ? $_ : '' } @$rec; # print Dumper($rec); if ( defined $rec->[index1] && $rec->[index1] ne '' && defined $rec->[index2] && $rec->[index2] eq '1' ) { if ($rec->[index3] == 1) { print "Crap\n" }; # +39 print "$rec->[index1] $rec->[index2] ", $rec->[index3], "\n"; # +40 print "OK\n"; } else { print "Not OK\n"; } # print Dumper($rec);

        And the output of an out of range index3:
        Use of uninitialized value at ./p09.pl line 39. Use of uninitialized value at ./p09.pl line 40. CSC.MIDRANGE.SERVER.SUPPORT 1
Re: split, Use of uninitialized value
by Tommy (Chaplain) on Jan 07, 2004 at 03:24 UTC
    The code below will suppress the warnings, but your question is so vague that it almost surely won't accomplish the desired end. What is going on?
    $rec->[IMP_WG] = defined $rec->[IMP_WG] ? $rec->[IMP_WG] : ''; $rec->[CSC_HAN] = defined $rec->[CSC_HAN] ? $rec->[CSC_HAN] : ''; $rec->[CLASSIF] = defined $rec->[CLASSIF] ? $rec->[CLASSIF] : ''; $rec->[SRV_PLT] = defined $rec->[SRV_PLT] ? $rec->[SRV_PLT] : ''; print STDERR "$rec->[IMP_WG] $rec->[CSC_HAN]\n"; if ( $rec->[IMP_WG] ne '' && $rec->[CSC_HAN] eq '1' ) { print "$rec->[CLASSIF] $rec->[IMP_WG] $rec->[SRV_PLT]\n"; }
    --
    Tommy Butler, a.k.a. TOMMY
    
      Too much typing, you could do with a one-liner instead. I ++'ed you anyhow because the idea is good. ;-)
      use strict; use Data::Dumper; my $rec = [ undef, 1, '', 2, 0 ]; @$rec = map { defined($_) ? $_ : '' } @$rec; print Dumper($rec); __END__ # ---output --- $VAR1 = [ '', 1, '', 2, '0' ];
Re: split, Use of uninitialized value
by ysth (Canon) on Jan 07, 2004 at 04:35 UTC
    That if ought not to produce warnings. If $rec->[IMP_WG] or $rec->[CSC_HAN] is undefined, the warning should show the print STDERR line.

    Is it possible that you have an elsif clause? Use of an undef value in it will produce a warning giving the line number of the if, since that is the beginning of the statement.

A reply falls below the community's threshold of quality. You may see it by logging in.