I have a file revs.pm
:
my %vers = ( foo => "bar" );
And another file like importer.pl
:
use revs;
How can I access %vers
from importer.pl
?
I have a file revs.pm
:
my %vers = ( foo => "bar" );
And another file like importer.pl
:
use revs;
How can I access %vers
from importer.pl
?
Create a proper module and change the my keyword to our:
# revs.pm
package revs;
our %vers = ( foo => "bar" );
1; # Perl modules need to return a boolean "true" value.
# importer.pl
use revs;
print $revs::vers{foo} . "\n";
Another conventional way is to use the Exporter module in your package, and export the variable:
package revs;
use strict;
use warnings;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT = qw(%vers);
our %vers = (foo=>'bar');
1;
This avoids having to use the package name when referring to the variable from importer.pl
:
use strict;
use warnings;
use Data::Dumper;
use revs;
print Dumper(\%vers);
One disadvantage is that you must make sure your variable name is unique in order to avoid name collisions.
Alternatively, you could just not couple parts of your program with a global variable. Consider what happens when you use this hash in one module:
package Foo;
use MyApp::Versions qw(%versions); # i'm going to pretend that you didn't call the module "revs".
some_function {
while(my ($k, $v) = each %versions){
return if $some_condition;
}
}
And then in some other module:
package Bar;
use MyApp::Versions qw(%versions);
some_other_function {
while(my ($k, $v) = each %versions){
print "$k => $v\n";
}
}
And then use both modules:
use Foo;
use Bar;
some_other_function;
some_function;
some_other_function;
Depending on $some_condition
, some_other_function produces different
results each time you call it. Have fun debugging that. (This is
more of an each
problem than a global state problem; but by exposing
the internal implementation, you allow your callers to do things that
you didn't intend, and that can easily break your program.)
It's also a pain to rewrite Foo and Bar when you change the hard-coded hash to an on-demand database lookup, for example.
So the real solution is to design a proper API, and export that instead of the entire variable:
package MyApp::Versions;
use strict;
use Carp qw(confess);
use Sub::Exporter -setup => {
exports => ['get_component_version'],
};
my %component_versions = ( foo => 42 ); # yes, "my", not "our".
sub get_component_version {
my ($component) = @_;
return $component_versions{$component} ||
confess "No component $component!"
}
1;
Now your module is easier to use:
package Foo;
use MyApp::Versions qw(get_component_version);
sub some_function {
die 'your foo is too old'
unless get_component_version('foo') >= 69;
return FooComponent->oh_hai;
}
Now some_function can't mess up some_other_function, and when you change the implementation of get_component_version, the rest of your program won't care.