Reputation: 37085
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 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)
Upvotes: 0
Views: 383
Reputation: 64909
$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";
}
Upvotes: 14
Reputation: 8849
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};
Upvotes: 5