You need to find out the current or calling package.
The
__PACKAGE__
symbol returns the package that the code is currently being compiled into. This doesn't interpolate into double-quoted strings:
print "I am in package __PACKAGE__\n"; # WRONG! I am in package __PACKAGE__
Needing to figure out the caller's package arose more often in older code that received as input a string of code to be
eval
uated, or a filehandle, format, or directory handle name. Consider a call to a hypothetical
runit
function:
package Alpha; runit('$line = <TEMP>'); package Beta; sub runit { my $codestr = shift; eval $codestr; die if $@; }
Because
runit
was compiled in a different package than was currently executing, when the
eval
runs, it will act as though it were passed
$Beta::line
and
Beta::TEMP
. The old workaround was to include your caller's package first:
package Beta; sub runit { my $codestr = shift; my $hispack = caller; eval "package $hispack; $codestr"; die if $@; }
That approach only works when
$line
is a global variable. If it's lexical, that won't help at all. Instead, arrange for
runit
to accept a reference to a subroutine:
package Alpha; runit( sub { $line = <TEMP> } ); package Beta; sub runit { my $coderef = shift; &$coderef(); }
This not only works with lexicals, it has the added benefit of checking the code's syntax at compile time, which is a major win.
If all that's being passed in is a filehandle, it's more portable to use the
Symbol::qualify
function. This function takes a name and package to qualify the name into. If the name needs qualification, it fixes it; otherwise, it's left alone. But that's considerably less efficient than a
*
prototype.
Here's an example that reads and returns n lines from a filehandle. The function qualifies the handle before working with it.
open (FH, "< /etc/termcap") or die "can't open /etc/termcap: $!"; ($a, $b, $c) = nreadline(3, 'FH'); use Symbol (); use Carp; sub nreadline { my ($count, $handle) = @_; my(@retlist,$line); croak "count must be > 0" unless $count > 0; $handle = Symbol::qualify($handle, (
caller()
)[0]); croak "need open filehandle" unless defined fileno($handle); push(@retlist, $line) while defined($line = <$handle>) && $count--; return @retlist; }
If everyone who called your
nreadline
function
passed in the filehandle as a typeglob
*FH
, as a glob reference
\*FH
, or using FileHandle or IO::Handle objects, you wouldn't need to do this. It's only the possibility of a bare
"FH"
that requires qualification.
The documentation for the standard Symbol module, also found in
Chapter 7
of
Programming Perl
; the descriptions of the special symbols
__FILE__
,
__LINE__
, and
__PACKAGE__
in
perldata
(1);
Recipe 12.12
Copyright © 2001 O'Reilly & Associates. All rights reserved.