SPUG: Confusing behaivior with exported variables
Jacinta Richardson
jarich at perltraining.com.au
Mon Mar 23 16:31:49 PDT 2009
As far as I can tell, your code works fine - by accident. So the only theory I
have is that you might be looking at the hash before it's been populated. The
code, with scaffolding that I'm using is:
########################################
# Darley/Supers.pm
package Darley::Supers;
use Data::Dumper;
BEGIN {
# This line creates the lexical variable and then it's discarded
# at the end of the block
my (%CurrentUser);
use Exporter ();
@ISA = qw(Exporter);
# This cannot export lexicals, so %CurrentUser here is the package
# variable so far undeclared. The ampersands are best omitted.
@EXPORT = qw(%CurrentUser &Power &Challenge &GetUser &GetOrg
&GetCity);
}
sub SetCurrentOrgSetting
{
my (%Args) = @_;
# Args: Setting = Setting to store
# Value = Value to store
#StoreOrgSetting(
# OrgID => $CurrentUser{Org}{org_id},
# Setting => $Args{Setting},
# Value => $Args{Value}
#);
# Since there isn't a lexical %CurrentUser in scope, this must be the
# package variable
$CurrentUser{Org}{Settings}{ $Args{Setting} } = $Args{Value};
return 1;
}
sub Show
{
print Dumper \%CurrentUser;
}
1;
########################################
# test.pl
use Darley::Supers qw(%CurrentUser);
use strict;
use Data::Dumper;
print "Before setting\n";
print Dumper \%CurrentUser;
Darley::Supers::SetCurrentOrgSetting(Setting => "ABC", Value => 123);
print "After setting\n";
print Dumper \%CurrentUser;
print "Module internals\n";
Darley::Supers::Show();
##########################
# Output:
Before setting
$VAR1 = {};
After setting
$VAR1 = {
'Org' => {
'Settings' => {
'ABC' => 123
}
}
};
Module internals
$VAR1 = {
'Org' => {
'Settings' => {
'ABC' => 123
}
}
};
########################################
Now you don't actually need that BEGIN block in your module at all, because all
you're doing is declaring a couple of things. If you were calling a method that
absolutely had to be called before the rest of the module was compiled, then
you'd put it in a BEGIN block.
Here's the strict compliant, non-BEGIN way of writing the same module:
########################################
# Darley/Supers.pm
package Darley::Supers;
use strict;
use Data::Dumper;
# use base qw(Exporter) does the same as use Exporter; our @ISA = qw(Exporter);
use base qw(Exporter);
# These don't need to be in a begin block, they're just declarations.
# Ampersands are not required to denote subroutines
our @EXPORT = qw(%CurrentUser Power Challenge GetUser GetOrg GetCity);
our (%CurrentUser);
sub SetCurrentOrgSetting
{
my (%Args) = @_;
# Args: Setting = Setting to store
# Value = Value to store
#StoreOrgSetting(
# OrgID => $CurrentUser{Org}{org_id},
# Setting => $Args{Setting},
# Value => $Args{Value}
#);
$CurrentUser{Org}{Settings}{ $Args{Setting} } = $Args{Value};
return 1;
}
sub Show
{
print Dumper \%CurrentUser;
}
1;
########################################
With the same test script, this yields the same output as above.
All the best,
J
--
("`-''-/").___..--''"`-._ | Jacinta Richardson |
`6_ 6 ) `-. ( ).`-.__.`) | Perl Training Australia |
(_Y_.)' ._ ) `._ `. ``-..-' | +61 3 9354 6001 |
_..`--'_..-_/ /--'_.' ,' | contact at perltraining.com.au |
(il),-'' (li),' ((!.-' | www.perltraining.com.au |
More information about the spug-list
mailing list