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

Now that I've lured you in with such an inflammatory title (g)...
I have a script broken into several pieces. For now, consider 'main.pl' and 'foo.pl' the only players on the stage for simplicity.
I have, in main.pl, declared my %hash. Later on in main.pl, I'm accessing $hash{$foo}{gne} successfully.For some error testing, I was attempting to force $hash{member}{gne} to a particular value in a sub located in foo.pl -- imagine my surprise when I find that, in foo.pl, %hash has no members. With the help of the usual gang, they point me to use vars qw (%hash) or our %hash depending on version & religious preference. One alteration later, and problems solved. However, something bothers me : if my %hash is scoped in main, and exists only in main, why doesn't perl spit out a warning or error when attempting to use %hash in foo.pl? I've got use strict enabled in main.pl, so it seems that such errors would be caught on compilation.

Replies are listed 'Best First'.
(tye)Re: our/my inconsistency.
by tye (Sage) on Jan 02, 2001 at 23:23 UTC

    use strict.pm is "scoped" so that it won't affect another file, even if you include it with require and it doesn't have a package statement. That causes the two file scopes to share the same package globals. But they don't share non-global things such a my variables or the settings from use strict.pm.

    Update: Also, use vars marks a variable as OK to strict.pm by tagging it as having been "imported". So use vars qw(%hash); "imports" %hash into the main:: package so that any use of %hash in the main:: package will not generate an error, even if that use was done from within another file.

    our doesn't mark %main::hash as having been imported but instead makes a lexical %hash (much like what my %hash does) that is aliased to %main::hash. So this won't affect other files that use %hash while in package main::. If you put our inside a block, then it won't even affect uses of %hash outside of that scope (but this is often a bad idea).

            - tye (but my friends call me "Tye")
      It looks like strict and warnings won't be entirely strict on subroutines and my.
      use strict; use warnings; my %hash = (one => "one", two => "two", three => "three" ); print "$hash{one}\n"; test(); exit; sub test { for (keys %main::hash) { print "$_ $main::hash{$_}\n"; } }
      This will print one.
      Substituting our for my will print something more expected.
      Interesting behaviour.
      Update:
      Try it out with arrays and a scalar.
      An array will warn of a var used once.
      A scalar will warn of unused var and die because of uninialized variable.
      Update++: Questions like this and the explanations from people like danger and tye really are cool. They show the inner workings of Perl and point out the nuances.

        my %hash does nothing to %main::hash, even if you are in package main. That is why "package variables" are also called "globals" and "my variables" are called "lexicals". Lexical variables are not in any symbol table. For example:

        package one; my $x= "hi"; package two; print "$x\n"; # prints "hi"
        This also illustrates a "feature" of our (that might be useful but could also be a source of problems):
        package one; our $x= "hi"; use vars qw($y); $y= "lo"; package two; print "$one::x $one::y\n"; # prints "hi lo" print "$x\n"; # prints "hi" print "$y\n"; # prints nothing # and would give an error under C<use strict>

                - tye (but my friends call me "Tye")

        Strict means you must declare your variables with my(), our(), or 'use vars', or use fully qualified package names. Using our() or 'use vars' is just a way of saying we want a global variable but we don't want to have to use the fully qualified name all the time -- you do not have to declare globals that way if you do use fully qualified names (as you do in your sub).

        Your example has two hashes: the global %main::hash (created on the fly in your subroutine) and the lexical %hash (declared near the top with the my() statement).

        No warnings are produced by your sub because the main::hash is referenced twice (no 'used only once' warning), and the print() never executes because there are no keys to loop over (no 'unitialized' warnings).

      ah, so I'm relying on some side effects of use vars that our doesn't possess.
Re: our/my inconsistency.
by repson (Chaplain) on Jan 03, 2001 at 06:48 UTC
    Other people have given you good advice on how to solve your problem directly. The other thing you need to think about is your application design.

    Accessing global vars between different files can be a bad or troublesome practice. If you want to change the name of the variable or want to perform the same action on two different hashes, you will need to edit multiple files referencing these global hashes, creating more work and errors which may not be detected and fixed easily.

    Instead you can pass the hash by reference to a subroutine in the other file(s) so you can maximise code reuse and only need to maintain one copy of the variable name, and eventually generate more flexibility.