From my main program I require a file containing a package, and then call a subroutine from that package:
while($somecondition){
require( 'people.pm' );
my $result = PERSON::stuff($args);
}
The PERSON package has multiple subs and some 'our' variables declared:
package PERSON;
our $name;
our ...
sub stuff {
...
}
In my understanding of other more object oriented languages you would need to declare a new object instance, maybe with its own constructor/initialization functions to use "package" variables. That doesn't seem to be the case here with Perl.
I'm dealing with legacy code so I don't want to change much, I just want to understand when the package variables ($name) come into existence, and when are they returned to memory from the perspective of the main program.
Would putting a PERSON::stuff() call after the while loop have new package variables? After calling a single function inside a package do the package variables live until the end of the program?
The question mixes up some concepts so let's first address what appears to be the main issue: If a package is require
'd inside some scope, what of it outside of that scope?
In short, (dynamical global) symbols from the package are accessible everywhere in the unit in which it is require
'd, via their fully qualified names.†
Let's try with an example
use warnings;
use strict;
use feature 'say';
TEST_SCOPE: {
say "In scope, in ", __PACKAGE__;
require TestPack;
#hi(); # "Undefined subroutine &main::hi called..."
TestPack::hi(); # ok
#say $global; # $global ... who??
say $TestPack::global; # ok
say "Leaving scope\n";
};
say "--- in ", __PACKAGE__;
TestPack::hi(); # ok
say $TestPack::global; # ok
File TestPack.pm
:
package TestPack;
use warnings;
use strict;
use feature 'say';
#use Exporter qw(import); # This is normally done to export symbols
#our @EXPORT_OK = qw(hi); # (unless the package is a class)
our $global = 7;
sub hi { say "hi from ", __PACKAGE__ }
1;
One needs to use fully qualified names for those symbols as they weren't imported. If the package exports symbols and we import some‡ then they go into the calling package's namespace so in the example above they'd be available in main::
, so they can be accessed by any code in the interpreter by their exported names (hi
, no need for TestPack::hi
). One cannot access lexical variables from that package (created with my
, our
, state
)§.
This also works if instead of the mere block (named TEST_SCOPE
) we introduce another package, and require
our TestPack
inside of it.
...
package AnotherPack {
require TestPack;
...
1;
};
...
TestPack::hi(); # ok
...
(That package
should be inside a BEGIN
block really, what doesn't change the main point here.) Global symbols from TestPack
are still accessible in main::
, via their fully qualified names. The exported names, which we import along with require
, are then available as such in this package, but not in main::
.
Comments on the question
Package name (PERSON
) and the filename for it (person.pm
) have to agree. For example, the namespace (==package) Person
is defined in the file Person.pm
This is about basics related to require-ing a package; it has nothing to do with object-oriented notions. (Even though, a class is firstly a package. See perlootut and perlobj.) Also see Packages in perlmod and our.
If you were to use a package that bless-es, the returned object (instance) is (assigned to) a lexical variable. As such, it doesn't exist outside of the scope. The package itself, though, is visible just as shown above but in object-oriented work we don't want to poke at a package's insides, but rather use methods via objects.
So yes, to work with that package outside of the scope in which it is require
-ed you'd need to instantiate an object in that other scope as well. That would still work much like the example above -- we can use the package name, outside of scope in which it was required, to instantiate an object (try!), even though I'd raise questions of such design (see next)
This hints at a convoluted design though, bringing in packages inside scopes, at runtime (via require
); what is the context? (And I hope it's not really in a while
loop.)
† Print out the main's symbol table, %main::
(using Data::Dumper
for example) and we find
"TestPack::" => *main::TestPack::
along with all other symbols from TestPack
namespace.
‡ If a package exports symbols and we require
the package then we can import by
require Pack::Name;
Pack::Name->import( qw(subname anothername ...) );
§ Note that our
creates a lexical which is an alias for a package variable, which is accessible.