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