Marc Ortiz Torres
Marc Ortiz Torres

Reputation: 11

Perl -- uninitialized variable

What is going on? I've created a simple program to read the lines and prints on a file the output. But it throws some errors...

Here's the code and the explanation of it is on the comments:

use warnings;
use List::MoreUtils qw(indexes);

my @array_words = ();
my @array_split = ();
my @array_of_zeros = (0);
my $index = 0;

open my $info, 'models/busquedas.csv';
open my $model, '>>models/model.txt';

#First while is to count the words and store it into an array
while( my $line = <$info>)  {
    @array_split = regex($line);
    for (my $i=0; $i < scalar(@array_split); $i++) {
            # Get the index if the word is repeated
        $index = indexes { $_ eq $array_split[$i] } $array_words[$i];
            # if the word is not repeated then save it to the array by 
            # checking the index
        if ($index != -1){ push(@array_words, $array_split[$i]); }
    }
}

print $model @array_words;

sub regex{
    # get only basic info like: 'texto judicial madrid' instead of the full url
    if ($_[0] =~ m/textolibre=/ and 
        $. < 3521239 && 
        $_[0] =~ m/textolibre=(.*?)&translated/) {
        return split(/\+/, $_[0]);
    }
}

And the errors that I don't understand are:

Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12216.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12216.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12216.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12217.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12217.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12217.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12217.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12217.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12218.
Use of uninitialized value $index in numeric ne (!=) at classifier.pl line 21, <$info> line 12218.

Why uninitialized $index ? I have declared it and initialized it with a 0 value! How can I fix this?

Upvotes: 1

Views: 1026

Answers (2)

Borodin
Borodin

Reputation: 126722

As has been observed, the indexes subroutine does't work like that. It returns a list of indices for which the block evaluates to true. It is wrong to use it in scalar context like this.

If you were to use a library for this, you would want any - also from List::MoreUtils. The code would look like this

while( my $line = <$info>)  {
    @array_split = regex($line);
    for my $word (@array_split) {
      push @array_words, $word unless any { $_ eq $word } @array_words;
    }
}

However I think you want something much simpler. From my understanding of your code a Perl hash will do what you need.

I have refactored your program like this. I hope it helps.

Essentially, each "word" in the line is pushed onto @array_words if it isn't already in the hash.

You also appear to have a bug in your regex subroutine. The statement

return split(/\+/, $_[0]);

splits the whole line and returns the result. I think it should split just the query part of the URL that you have just extracted, like this

return split /\+/, $1;

Ordinarily you should check to see that open calls succeeded. Adding the autodie pragma does this implicitly for you.

use strict;
use warnings;
use autodie;

open my $info,  '<',  'models/busquedas.csv';
open my $model, '>>', 'models/model.txt';

my %unique_words;
my @array_words;

#First while is to count the words and store it into an array
while( my $line = <$info>)  {
  for my $word (regex($line)) {
    push @array_words, $word unless $unique_words{$word}++;
  }
}

print $model "$_\n" for @array_words;

sub regex {

  my ($line) = @_;

  # get only basic info like: 'texto judicial madrid' instead of the full url
  return unless $line =~ /textolibre=/ and $. < 3521239;
  if ( $line =~ /textolibre=(.*?)&translated/ ) {
    return split /\+/, $1;
  }
}

Upvotes: 0

choroba
choroba

Reputation: 241748

You have initialized the variable with zero, but then you change its value with

$index = indexes { $_ eq $array_split[$i] } $array_words[$i];

The function probably returns an undef (because $array_words[$i] does not eq $array_split[$i]). It would return one otherwise, as there is only one element in the list.

BTW, initializing a variable outside of a loop is a bad practice if you do not need its value outside the loop. You can declare my $index at the same line where you populate it with indexes.

Upvotes: 1

Related Questions