views:

152

answers:

2

I have a module Routines.pm:

package Routines;
use strict;
use Exporter;

sub load_shortest_path_matrices {
  my %predecessor_matrix = shift;
  my %shortestpath_matrix = shift;
  ...
}

From another script I call the the sub in the module, passing in arguments which happen to have the same name:

use Routines;
use strict;

my %predecessor_matrix = ();
my %shortestpath_matrix =();  
&Routines::load_shortest_path_matrices($predecessor_matrix, $shortestpath_matrix);

However, this doesn't compile and I get

Global symbol "$predecessor_matrix" requires explicit package name

type of errors. Is it not possible to give the same name to variables in different scopes like this in Perl? (I'm from a C background)

+5  A: 

you are declaring the hash %predecessor_matrix but are trying to pass the scalar $predecessor_matrix. The hash exists, the scalar doesn't.

Maybe you want to pass references to the hashes?

Routines::load_shortest_path_matrices(\%predecessor_matrix, \%shortestpath_matrix);


Here's another way to code it:

use strict;
use warnings;
use Routines;

my $predecessor_matrix = {};
my $shortestpath_matrix ={};  
Routines::load_shortest_path_matrices(  $predecessor_matrix
                                       , $shortestpath_matrix
                                      );


package Routines;
use strict;
use Exporter;

sub load_shortest_path_matrices {
  my $predecessor_matrix = shift;
  my $shortestpath_matrix = shift;
  ...
}

you can access the contents of the hashes like this

my $foobar=$shortestpath_matrix->{FOOBAR};
lexu
Chas. Owens
lexu
ysth
+13  A: 

$predecessor_matrix is a scalar and %predecessor_matrix is a hash. Different types in Perl (scalar, array, hash, function, and filehandle) have different entries in the symbol table, and, therefore, can have the same name.

Also, you have a problem in your function. It expects to be able to get two hashes from @_, but a hash in list context (such as in the argument list of a function) yields a list of key value pairs. So, both %predecessor_matrix and %shortestpath_matrix will wind up in the %predecessor_matrix of the function. What you need to do here is to use references:

package Routines;
use strict;
use Exporter;

sub load_shortest_path_matrices {
    my $predecessor_matrix  = shift;
    my $shortestpath_matrix = shift;
    $predecessor_matrix->{key} = "value";
    ...
}

and

use Routines;
use strict;

my %predecessor_matrix; 
my %shortestpath_matrix;  
Routines::load_shortest_path_matrices(
    \%predecessor_matrix,
    \%shortestpath_matrix
);

However, passing in structures to load as arguments is more C-like than Perl-like. Perl can return more than one value, so it is more common to see code like:

package Routines;
use strict;
use Exporter;

sub load_shortest_path_matrices {
    my %predecessor_matrix;
    my %shortestpath_matrix;
    ...
    return \%predecessor_matrix, \%shortestpath_matrix;
}

and

use Routines;
use strict;

my ($predecessor_matrix, $shortestpath_matrix) =
    Routines::load_shortest_path_matrices();

for my $key (keys %$predecessor_matrix) {
    print "$key => $predecessor_matrix->{$key}\n";
}
Chas. Owens