Home > Software engineering >  Where is the uninitialized value in the compare function?
Where is the uninitialized value in the compare function?

Time:03-30

I tried to find the error myself, but don't see it. The following code produces warnings (same problem in Perl 5.18.2 and 5.32.1).

Use of uninitialized value in numeric comparison (<=>) at test.pl line 14.

while the comparison function of the sort is performed (and, as a consequence, the sort operation is not performed correctly). As far as I see, no value of the hash is initial, they all have defined numeric values.

use strict;
use warnings;

# Sort the occurrences of letters in a list of words, highest count first. 

my @words = ('ACGT','CCGT','CATG');  # Just an example
my $a = join '',@words;
my $l = length $a;
my %count = ();  

for (my $i = 0; $i < $l; $i  )  {
  my $x = substr( $a, $i, 1);
  $count{$x}  ;
}

for my $x (sort { $count{$b} <=> $count{$a} } keys %count) {
  print "$x: $count{$x}\n";
} 

Remark : it didn't help adding the hash element creation line before incrementing it with the $count{$x} ; statement - same result (expectedly, as undef counts like 0 for the increment operation):

...
  $count{$x} = 0 unless defined $count{$x};
  $count{$x}  ;
...

CodePudding user response:

Normally, the sort function uses two package variables called $a and $b to do the sorting. Specifically, sort sets the variables called $a and $b on the current package to be the current sort values. Those are not arguments to your { $count{$b} <=> $count{$a} } block; they're global variables in the current package.

Now, $b is fine. Since you never do anything else with it, Perl picks up the package variable just fine. But you declared a lexical (my) variable called $a earlier in your code, and that lexical is shadowing the package variable.

So sort is setting a variable called, effectively, $YourPackage::a, and your code is accessing a local variable called my $a, which is unrelated to the other one.

You can fix this by changing the my $a = join '',@words; variable to be called something else, and in fact you should probably do that. The names $a, $b, and $_ are used for things like this indiscriminately in Perl for historical reasons, so it's probably best to never have your own variables named any of those names.

But if you don't want to (or can't) change any of the rest of the code, you can expose the package variable with our.

for my $x (sort { our $a; $count{$b} <=> $count{$a} } keys %count) {
  ...
}
  •  Tags:  
  • perl
  • Related