sirrobert has asked for the wisdom of the Perl Monks concerning the following question:

Hi all. Been reading for a while, never posted before.

I'm trying to create a variable that exists in package space that is persistent without an instantiation of any objects. I'd like to accomplish something like a public static variable.

Here's a simplest case script:

foo.pl

#!/usr/bin/perl use strict; use lib '.'; use Bar; ### Before and after snapshots. print 'var before setting: (' . $Bar::package_variable . ")\n"; $Bar::package_variable = 'Ogopogo'; print 'var after setting: (' . $Bar::package_variable . ")\n"; ### From an object. my $obj = new Bar( ); print 'var from obj--unqualified: (' . $obj->{'unqualified'} . ")\n"; print 'var from obj--qualified: (' . $obj->{'qualified'} . ")\n"; print "\nAddresses:\n"; print '$Bar::package_variable '.\$Bar::package_variable."\n"; print '$obj->{"unqualified_ref"} '.\${$obj->{'unqualified_ref'}}."\n"; print '$obj->{"qualified_ref"} '.\${$obj->{'qualified_ref'}}."\n"; exit;

And the module it's using:

Bar.pm

package Bar; our $package_var; sub new { my $class = shift; my $self = {}; bless $self, $class; $self->{'unqualified'} = $package_var; $self->{'qualified'} = $Bar::package_var; $self->{'unqualified_ref'} = \$package_var; $self->{'qualified_ref'} = \$Bar::package_var; return $self; } 1;

And the output of running the script:
Output of $>./foo.pl

Package var before setting: () Package var after setting: (Ogopogo) Package var from obj--unqualified: () Package var from obj--qualified: () Addresses: $Bar::package_variable SCALAR(0x815363c) $obj->{"unqualified_ref"} SCALAR(0x8188950) $obj->{"qualified_ref"} SCALAR(0x8188950)
Why doesn't object instantiation work as I'm expecting? The script seems to be able to interact with the package variable, but the module doesn't? From the "Addresses" section, it appears that they're looking in two different places, but I'm not sure why -- especially since the qualified and unqualified versions are looking in the same place, from within the package.

Help!

Thanks =)

Replies are listed 'Best First'.
Re: Accessibility of package-level variables
by ikegami (Patriarch) on Apr 16, 2008 at 14:53 UTC

    You set $Bar::package_variable in foo.pl, but read $Bar::package_var in Bar.pm

    From the "Addresses" section, it appears that they're looking in two different places

    As it should. The package variable and the hash element are two different variables.

    Update: I got confused by the \${...} no-op.

      Well crud.

      Thanks =)

Re: Accessibility of package-level variables
by NetWallah (Canon) on Apr 16, 2008 at 17:39 UTC
    Unfortunately, "use strict" did not help you in this case.

    You have a simple typo - correcting that makes it work as you expect.

    In main, you call it "package_variable" (injecting this new, undeclared variable into Bar's namespace), whereas in Bar, you reference apparently the same intended variable, as "$package_var".

    The different addresses for the different variables were a clue.

    ikegami can probably un-strikeout (or is it un-redact?) his comment, which had the right idea.

         "How many times do I have to tell you again and again .. not to be repetitive?"

Re: Accessibility of package-level variables
by Narveson (Chaplain) on Apr 16, 2008 at 22:15 UTC
    I'm trying to create a variable that exists in package space that is persistent without an instantiation of any objects. I'd like to accomplish something like a public static variable.

    Many of us who worked our way through the Camel book had a hard time coming to terms with the current standard advice about package variables:

    don't use them.

    See e.g. Dominus's excellent article Coping with Scoping.

    You can still have your public static variable:

    use strict; my $public_static_variable;

    Write subroutines in the same file to grant read and write access to this global public static variable:

    package Bar; sub get_public_static_value { return $public_static_variable; } sub set_public_static_value { my ($new_value, $options_ref) = @_; # validate the new value # respond to the options # log the modification $public_static_variable = $new_val; }

    Now your client code in other files can invoke Bar::get_public_static_value() and Bar::set_public_static_value($foo), but you get the spell-checking benefits of use strict and the serenity of knowing where to focus your debugging in case the static variable acquires an unexpected value.