Skip to content
VLSI Mentor

Perl Part I · Module 12 · Modules and Packages

Package Variables, our, and Why my Is Different

Chapter 12.2 established that a package is a namespace and not a scope, and left a loose end: if a package does not limit how long anything lives or who can see it, what does? The answer is the declaration keyword, and the two available are less similar than their syntax suggests. our attaches a variable to the package, which means every other file in the program can read it and write it by its full name. my attaches it to the file or block, which means nothing outside can reach it at all — not with a full name, not with any name. Both are measured here, including the consequence most people have not thought through: a module setting declared with our is writable by any caller at any time, and section three shows a caller changing one and the module's own code reporting the new value. The chapter then argues for the third option named in the canonical description, which is neither keyword on its own but a private variable with a small subroutine in front of it.

Advanced13 min readPerlPart IModules

Part I · Module 12 · Chapter 12.7 · Package Variables, our, and Why my Is Different

1. One Is Reachable, One Is Not

A module declares two variables, one with each keyword, and a script in a different file tries to read both.

Azvya Education Pvt. Ltd.VLSI Mentor
our-vs-my.pl
use strict;
use warnings;
use File::Temp qw(tempdir);
use File::Spec;

my $dir = tempdir(CLEANUP => 1);
mkdir File::Spec->catdir($dir, "Demo");

open my $fh, ">", File::Spec->catfile($dir, "Demo", "Vars.pm") or die $!;
print $fh <<'M';
package Demo::Vars;
use strict;
use warnings;

our $PUBLIC  = "declared with our";
my  $PRIVATE = "declared with my";

sub show_private { return $PRIVATE }
1;
M
close $fh;

unshift @INC, $dir;
require Demo::Vars;

printf "\$Demo::Vars::PUBLIC   : %s\n", $Demo::Vars::PUBLIC;
{
    no strict 'refs';
    no warnings 'uninitialized';
    printf "\$Demo::Vars::PRIVATE  : [%s]\n", $Demo::Vars::PRIVATE;
}
printf "via its own accessor  : %s\n", Demo::Vars::show_private();
print  "\nour publishes the name; my is unreachable from outside the file\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
$Demo::Vars::PUBLIC   : declared with our
$Demo::Vars::PRIVATE  : []
via its own accessor  : declared with my

our publishes the name; my is unreachable from outside the file

The our variable came out of another file by its full name. The my variable came out empty.

That empty value deserves a precise explanation, because it is not "access denied". $Demo::Vars::PRIVATE is a perfectly legal name for a package variable in Demo::Vars — it simply refers to a variable that was never created. The module's my $PRIVATE is a different thing entirely, living in the file's lexical scope, with no entry in the package at all. There is no name you could write from outside that would reach it.

The third line proves the variable does exist and does hold its value: the module's own subroutine, compiled inside that lexical scope, can see it. That is the whole mechanism of a private module variable, and Chapter 12.11 builds on it.

2. Which One for a Module Setting?

Three places a module setting can live

Three ways to store a module setting: our which any caller can write, my which is private but unreachable, and a small accessor subroutine over a private variable which gives both privacy and validation.a module settingwhere should it live?our $LEVELany caller can write itmy $LEVELprivate to the filea small accessorprivate plus validation12
The first option publishes the setting to the whole program, which is why it is marked as the risk. The second makes it genuinely private but then unreachable by the caller who needs to change it. The third adds four lines and gets privacy, a single point of change, and the chance to reject a bad value before it is stored.

The canonical description says a module's settings "usually want neither" of the two keywords on their own, and the next two sections are the measurements behind that.

3. An our Setting Is Writable by Anyone

Azvya Education Pvt. Ltd.VLSI Mentor
anyone-can-change-it.pl
use strict;
use warnings;

package Demo::Log {
    our $LEVEL = "warn";
    sub level { return $LEVEL }
}

printf "module says level : %s\n", Demo::Log::level();

# A caller reaches in and changes it. Nothing stops this.
$Demo::Log::LEVEL = "debug";
printf "after a caller wrote to it : %s\n", Demo::Log::level();
print  "\nan 'our' setting is writable by anyone, from anywhere\n";
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
module says level : warn
after a caller wrote to it : debug

an 'our' setting is writable by anyone, from anywhere

A line of code outside the package assigned to the module's variable, and the module's own accessor now reports debug. No warning, no error, no mechanism to prevent it.

Sometimes that is the design. $Data::Dumper::Indent and $Data::Dumper::Sortkeys are exactly this, deliberately, and Chapter 7.12 set them that way. It is a documented, conventional interface for a module whose behaviour you tune globally.

Much more often it is an accident waiting to be found. The problems are concrete:

  • Any value can be stored. $Demo::Log::LEVEL = "dbeug"; is accepted, and the module discovers it later, somewhere else.
  • Any file can do it, including one you do not own, which makes the write impossible to find by reading the module.
  • The change is global and permanent for the rest of the run. A function that sets it for its own purposes has changed it for everything that follows — which is what Chapter 12.8's local exists to solve.
  • A typo in the name is legal, which is the next measurement.
Azvya Education Pvt. Ltd.VLSI Mentor
typo-not-caught.pl
use strict;
use warnings;

package Demo::Config {
    our $VERBOSE = 1;
}

# A correct read
printf "correct name : %s\n", $Demo::Config::VERBOSE;

# A TYPO in a fully-qualified name is a legal global that nobody set.
{
    no warnings 'uninitialized';
    printf "typo'd name  : [%s]\n", $Demo::Config::VERBOZE;
}
printf "did strict stop it : no -- a package variable name is always legal\n";

# Compare: a typo on a MY variable is a compile error
my $ok = eval 'my $local_only = 1; print $local_onlyy; 1';
printf "typo on a my var   : %s\n", ($ok ? "allowed" : "compile error");
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
correct name : 1
typo'd name  : []
did strict stop it : no -- a package variable name is always legal
typo on a my var   : compile error

The misspelt package name read as empty; the misspelt my name was a compile error. That asymmetry is the practical cost of use strict 'vars' not applying to fully-qualified names, which Chapter 12.2 mentioned and this measures.

To be fair to Perl, there is a partial net, and the output block above does not show it because it is a compile-time warning on stderr:

Name "Demo::Config::VERBOZE" used only once: possible typo

That is genuinely useful and worth knowing. It is also weaker than it looks: it fires only when the name appears exactly once in the file, so a typo you made twice — or one in a loop you wrote twice — is silent. And like the warning in Chapter 11.4, it is issued during compilation, so a $SIG{__WARN__} handler cannot intercept it.

4. The Third Option

Azvya Education Pvt. Ltd.VLSI Mentor
accessor-instead.pl
use strict;
use warnings;
use File::Temp qw(tempdir);
use File::Spec;

my $dir = tempdir(CLEANUP => 1);
mkdir File::Spec->catdir($dir, "Demo");
open my $fh, ">", File::Spec->catfile($dir, "Demo", "Safe.pm") or die $!;
print $fh <<'M';
package Demo::Safe;
use strict;
use warnings;

my $LEVEL = "warn";                         # private to this file

sub level {
    my ($new) = @_;
    if (defined $new) {
        die "bad level '$new'\n" unless $new =~ /^(?:warn|debug|quiet)$/;
        $LEVEL = $new;
    }
    return $LEVEL;
}
1;
M
close $fh;
unshift @INC, $dir;
require Demo::Safe;

printf "default            : %s\n", Demo::Safe::level();
printf "set to debug       : %s\n", Demo::Safe::level("debug");
my $ok = eval { Demo::Safe::level("nonsense"); 1 };
printf "set to nonsense    : %s", $ok ? "allowed\n" : "rejected -- $@";
printf "still              : %s\n", Demo::Safe::level();
{
    no strict 'refs'; no warnings 'uninitialized';
    printf "reachable as a package var : [%s]\n", $Demo::Safe::LEVEL;
}
Azvya Education Pvt. Ltd.VLSI Mentor
Captured output
default            : warn
set to debug       : debug
set to nonsense    : rejected -- bad level 'nonsense'
still              : debug
reachable as a package var : []

Four behaviours, all of them things the our version could not do.

The default is set once, in the module. No caller needs to know it exists.

Setting it goes through one subroutine, so there is exactly one place where the value changes and exactly one place to put a warn or a log line if you ever need to know who changed it.

A bad value is rejected — the pattern is Chapter 11.9's anchored alternation — and the last two lines confirm the variable still holds debug afterwards. A rejected write left the state untouched, which an our assignment cannot promise.

The variable is not reachable as a package variable, as the final [] shows. There is no back door.

The cost is four lines and one level of indirection, and the reason this chapter is rated Advanced is that recognising when that cost is worth paying is a judgement rather than a rule. The judgement: if the setting has valid and invalid values, or if you would ever want to know who changed it, write the accessor. If it is genuinely a global knob in the Data::Dumper tradition, our is honest and conventional.

Chapter 12.11 takes the same technique further, to a module holding a cache rather than a single setting.

5. Reading Which One You Are Looking At

A practical note, since most of your time goes on code you did not write.

our $X near the top of a module means the author intended $Package::X to be part of the interface, whether or not they documented it. Treat it as public and expect callers to be setting it.

my $X at file scope means the author intended it to be private, and only subroutines defined in that file can see it. If you need its value from outside, the module must grow an accessor — there is no way around it, and that is the point.

our $X inside a subroutine is a different and usually accidental thing: it declares the alias for that subroutine's scope only, while the variable itself is still the package global. It almost always means the author wanted my and reached for the wrong keyword, and it is worth flagging in review, because the variable survives between calls in a way the author likely did not intend.

And one more pattern: a fully-qualified assignment to another package's variable, such as $Other::Module::DEBUG = 1;, is a caller reaching in. It works, as section three measured. If you find one in your own codebase, the question is whether the module it points at should have offered an accessor instead.

6. What To Remember

  • our attaches the name to the package, so any file can read or write $Package::var. my attaches it to the file or block, and nothing outside can reach it.
  • $Package::PRIVATE for a my variable reads as empty, not as an error. It is a legal name for a package variable that was never created.
  • our is a declaration, not a creation. It declares a lexical alias to a package variable, which is why it satisfies use strict.
  • An our setting is writable by anyone, with any value, permanently. Measured: a caller assigned to it and the module's own accessor reported the new value.
  • A typo in a fully-qualified name is legal and reads as empty, where the same typo on a my variable is a compile error. use warnings does say used only once: possible typo on stderr — but only when the name appears exactly once.
  • The third option is a my at file scope plus a small subroutine. Measured: it gives a default, one place to change it, rejection of a bad value with the state intact, and no package-variable back door.
  • Write the accessor when the setting has invalid values or when you would ever want to know who changed it. our is honest for a genuine global knob.
  • our inside a subroutine is almost always a mistake for my.

Chapter 12.8 addresses the one problem the accessor does not solve: changing a global that is not yours — a built-in like the input record separator — for the duration of one block and having it put back afterwards, whatever happens in between.

Where this fits

Part of the Perl curriculum.