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

Is there a function similar to our that works across multiple files? I have separate packages in separate files, but really like the "globalness" of our variables when all the packages are in the same file.

Thanks.

Replies are listed 'Best First'.
Re: Our Across Multiple Files?
by davorg (Chancellor) on Dec 17, 2001 at 19:34 UTC

    You probably need to look at the docs for Exporter.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg

      test.pl --- require Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw($bar); use Blah qw($bar); $bar = 4; Blah::test(); Blah.pm ----- package Blah; sub test {print $bar}; 1;
      That doesn't work. I tried a few variations, but that one seemed the most correct based on the docs.
        test.pl --- #!/usr/bin/perl -w use strict; use Blah qw($bar test); $bar = 4; test(); Blah.pm ----- use strict; package Blah; require Exporter; use vars qw(@ISA @EXPORT_OK $bar); @ISA = qw(Exporter); @EXPORT_OK = qw($bar test); sub test {print $bar}; 1;
        --
        <http://www.dave.org.uk>

        "The first rule of Perl club is you do not talk about Perl club."
        -- Chip Salzenberg

Re: Our Across Multiple Files?
by robin (Chaplain) on Dec 17, 2001 at 22:28 UTC
    It's important to understand exactly what our does, then you'll see that you can use it across multiple files.

    our, like my, is a lexically-scoped declaration. That means it holds sway over a particular region of the source code -- from the declaration down to the end of the block that the declaration is in.

    The effect of an our declaration is a bit subtle. It allows you to use a global variable (i.e. a package variable) without having to qualify it with the name of the package. So far so good, but the complication arises when you change the current package within the scope of the our declaration.

    use strict; package foo; our $x; # Declare $x as an abbreviation for $foo::x $x = 23; package bar; print $x; # Still refers to $foo::x even # though we're now in package 'bar'

    When you understand that, you'll see how to use our across multiple files. The important thing is to make sure that the declaration is in the same package each time. For example:

    # This is test.pl use strict; our $foo = "Hello!\n"; use Bar; Bar->test();

    # This is Bar.pm use strict; our $foo; package Bar; sub test { print $foo; } 1;

    A more difficult question is why you'd want to do this. Using a global variable from within a package violates encapsulation. If you find yourself needing to do it, that's probably a sign that your code needs to be redesigned.

      I have a single DBH connection object, a single instance object, and others for a one-time project I'm working on myself. I know its not exaclty great technique, but because I'm the only one that will ever see it, I don't think it will hurt in the long run.

        You could just put it in package main, as in $main::db = new DB();, although it's one of those design choices that can get very deeply sedimented in a large project, and hard to change later.

        If you're feeling amibitious, why not try a singleton class, with a class method that returns the data you need?

        package GlobalVarsSingleton; my $instance; # a 'private' ctor sub _new { # init stuff } sub Instance { my ($class, %args) = @_; unless (defined $instance) { $instance = $class->_new(%args); return $instance; } else { return $instance; } }

        The singleton ensures that you'll only have one instance of the data per interpreter, and the calling code doesn't have to care where that data lives.

        The only remaining caveat is that code not meant to stick around sometimes does. I have code written as throw-away from year ago slightly tweaked and running in production on servers today. Oh, and that Unix thing so many people (including myself) love? The original was meant to be an in-house project...
Re: Our Across Multiple Files?
by hakkr (Chaplain) on Dec 17, 2001 at 22:49 UTC
    You could write an access routine to manipulate the variable in the package.
Re: Our Across Multiple Files?
by Anonymous Monk on Dec 17, 2001 at 22:11 UTC
    After trying to get it to work for about half an hour, I figured out my problem. It doesn't work when I use all capitalized variable names ($DBH, $ACCESS, etc.)

    Nothing in the docs about this. Is there a workaround? If not, any suggestions for a new global variable naming scheme?