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

I want to make use of a hash variable inside of a separate package file but it doesn't seem to really access the variable. It does work if I include the package in the same file (and change 'my' to 'our'). I've been searching for the answer for several hours now, and I really don't get it
#!/usr/bin/perl use strict; use warnings; require 'Config.pm'; print "Hash: ",%Config::amazon_config,"\n"; print "Host: ",$Config::amazon_config{'host'},"\n"; print "Name: ",$Config::amazon_config{name},"\n";
And the Config.pm file
package Config; my %amazon_config = ( 'name' => 'amazon', 'host' => 'localhost', 'user' => 'amazon', 'pass' => 'somepass', 'upload_path' => '/', 'file_types' => [ qw( jpg mobi ) ], ); 1;
When run it returns:
Hash: Use of uninitialized value in print at Objects.pl line 15. Host: Use of uninitialized value in print at Objects.pl line 16. Name:

Replies are listed 'Best First'.
Re: Package Variables
by Eliya (Vicar) on Mar 27, 2011 at 19:28 UTC

    Aside from the already mentioned naming problem, it's worth noting that lexical (my) variables are implicitly also file-scoped, and you can use fully qualified notation (like $Config::amazon_config{name}) only to access package variables  (which is why our works).

    In other words, even if you rename the package, you'd still have to use package variables in order to share them this way.

      Minor correction - my is block scoped (or more technically speaking "lexically" scoped) with the largest containing "block" (lexical unit) being the file. Example:

      use strict; use warnings; package Goo; my $x=100; print "package=", __PACKAGE__, " x=$x\n"; package Boo; { my $x=200; print "package=", __PACKAGE__, " x=$x\n"; } package Foo; print "package=", __PACKAGE__, " x=$x\n"; #outputs package=Goo x=100 package=Boo x=200 package=Foo x=100
      I didn't know that about the Config.pm perl module -- thanks.

      I didn't know that 'my' was scoped to a file, however I have tried using 'our' in the separate Config.pm file and it still doesn't work either. Only when the "package" is in the same file does 'our' work. Any shouldn't 'my' work in that situation as well?

      I just renamed my module to 'Config11.pm' and it works fine now. What a drag -- I didn't realize that Config.pm would collide. Why didn't perl warn me that I was stepping on a built in package of core significance? Or did perl just include the core "Config.pm" module and mine never actually got loaded?
        Why didn't perl warn me that I was stepping on a built in package of core significance? Or did perl just include the core "Config.pm" module and mine never actually got loaded?

        How would perl know that this is unintentional?

        If you write a new program and name it perl.exe, would your OS warn you that ./perl.exe is not C:\Perl\bin\perl.exe?

        @INC managment is like @PATH managment, the assumption is you know what you're doing

        $ cat Config.pm package Config; $VERSION=666666; 1; $ perl -MConfig -le " print $INC{q!Config.pm!}" C:/perl/5.12.2/lib/MSWin32-x86-multi-thread/Config.pm $ perl -le "print for @INC" C:/perl/site/5.12.2/lib/MSWin32-x86-multi-thread C:/perl/site/5.12.2/lib C:/perl/5.12.2/lib/MSWin32-x86-multi-thread C:/perl/5.12.2/lib . $ perl -I. -MConfig -le " print $INC{q!Config.pm!}" Config.pm $ perl -I. -le "print for @INC" . C:/perl/site/5.12.2/lib/MSWin32-x86-multi-thread C:/perl/site/5.12.2/lib C:/perl/5.12.2/lib/MSWin32-x86-multi-thread C:/perl/5.12.2/lib .
        Why didn't perl warn me that I was stepping on a built in package of core significance?
        That would make a good Perl::Critic policy. There is already Perl::Critic::Policy::Subroutines::ProhibitBuiltinHomonyms. I wonder how tough it would be to create a policy to look for Core module names.

        Update: on second thought, this would not be possible. I think the only thing that can be done is use something like findpm to search for duplicate modules in @INC.

Re: Package Variables
by Corion (Patriarch) on Mar 27, 2011 at 19:18 UTC

    Config (resp Config) is an existing Perl module. It's very unwise to name your module identical to it.

Re: Package Variables
by toolic (Bishop) on Mar 27, 2011 at 19:33 UTC
    You can debug this type of problem by dumping the %INC variable to make sure your package is coming from the file you think it is (as Corion has pointed out):
    use warnings; use strict; use Data::Dumper; require 'Config.pm'; print Dumper(\%INC);
      That's helpful, thanks.

      This is the first time I have worked with packages so I assumed the problem was some scoping issue I didn't understand. Hopefully I'll be able to read the signs more clearly next time. Thanks guys
Re: Package Variables
by wind (Priest) on Mar 27, 2011 at 20:12 UTC

    Consider using Exporter

    package MyConfig; use Exporter 'import'; @EXPORT = qw(); @EXPORT_OK = qw(%amazon_config); use strict; our %amazon_config = ( 'name' => 'amazon', 'host' => 'localhost', 'user' => 'amazon', 'pass' => 'somepass', 'upload_path' => '/', 'file_types' => [ qw( jpg mobi ) ], ); 1; __END__

    And your script:

    #!/usr/bin/perl use MyConfig qw(%amazon_config); use strict; use warnings; print "Host: ",$amazon_config{host},"\n"; print "Name: ",$amazon_config{name},"\n";

    Output

    Host: localhost Name: amazon
    - Miller