📄 ch10_01.htm
字号:
variables. (Special identifiers like <tt class="literal">_</tt> and<tt class="literal">SIG</tt> merely seem global because they default to the<tt class="literal">main</tt> package instead of the current one.)</p><p><a name="INDEX-2203"></a><a name="INDEX-2204"></a><a name="INDEX-2205"></a> The scope of a <tt class="literal">package</tt> declaration is from the declaration itselfthrough the end of the enclosing scope (block, file, or<tt class="literal">eval</tt>--whichever comes first) or until another<tt class="literal">package</tt> declaration at the same level, whichsupersedes the earlier one. (This is a common practice).</p><p><a name="INDEX-2206"></a>All subsequent identifiers (including those declared with <tt class="literal">our</tt>, butnot including those declared with <tt class="literal">my</tt> or those qualified with adifferent package name) will be placed in the symbol table belonging tothe current package. (Variables declared with <tt class="literal">my</tt> are independent ofpackages; they are always visible within, and only within, theirenclosing scope, regardless of any package declarations.)</p><p><a name="INDEX-2207"></a>Typically, a <tt class="literal">package</tt> declaration will be the first statement of afile meant to be included by <tt class="literal">require</tt> or <tt class="literal">use</tt>. But again, that'sby convention. You can put a <tt class="literal">package</tt> declaration anywhere you canput a statement. You could even put it at the end of a block, inwhich case it would have no effect whatsoever. You can switch into apackage in more than one place; a package declaration merely selectsthe symbol table to be used by the compiler for the rest of thatblock. (This is how a given package can span more than one file.)</p><p><a name="INDEX-2208"></a><a name="INDEX-2209"></a><a name="INDEX-2210"></a><a name="INDEX-2211"></a>You can refer to identifiers<a href="#FOOTNOTE-5">[5]</a> in other packages by prefixing("qualifying") the identifier with the package name and a doublecolon: <tt class="literal">$Package::Variable</tt>. If the package name is null, the<tt class="literal">main</tt> package is assumed. That is, <tt class="literal">$::sail</tt> is equivalent to<tt class="literal">$main::sail</tt>.<a href="#FOOTNOTE-6">[6]</a></p><blockquote class="footnote"><a name="FOOTNOTE-5"></a><p>[5] By identifiers, we mean thenames used as symbol table keys for accessing scalar variables, arrayvariables, hash variables, subroutines, file or directory handles, andformats. Syntactically speaking, labels are also identifiers, butthey aren't put into a particular symbol table; rather, they areattached directly to the statements in your program. Labels cannot bepackage qualified.</p></blockquote><blockquote class="footnote"><a name="FOOTNOTE-6"></a><p>[6] To clear up another bit of potentialconfusion, in a variable name like <tt class="literal">$main::sail</tt>, we use the term"identifier" to talk about <tt class="literal">main</tt> and <tt class="literal">sail</tt>, but not <tt class="literal">main::sail</tt>.We call that a variable name instead, because identifiers cannotcontain colons.</p></blockquote><p><a name="INDEX-2212"></a><a name="INDEX-2213"></a>The old package delimiter was a single quote, so in old Perl programsyou'll see variables like <tt class="literal">$main'sail</tt> and <tt class="literal">$somepack'horse</tt>. Butthe double colon is now the preferred delimiter, in part because it'smore readable to humans, and in part because it's more readable to<em class="emphasis">emacs</em> macros. It also makes C++ programmers feel like they knowwhat's going on--as opposed to using the single quote as the separator,which was there to make Ada programmers feel like they knew what'sgoing on. Because the old-fashioned syntax is still supported forbackward compatibility, if you try to use a string like <tt class="literal">"This is$owner's house"</tt>, you'll be accessing<tt class="literal">$owner::s</tt>; that is, the <tt class="literal">$s</tt>variable in package <tt class="literal">owner</tt>, which is probably not what you meant.Use braces to disambiguate, as in <tt class="literal">"This is ${owner}'s house"</tt>.</p><p>The double colon can be used to chain together identifiers in a packagename: <tt class="literal">$Red::Blue::var</tt>. This means the <tt class="literal">$var</tt> belonging to the<tt class="literal">Red::Blue</tt> package. The <tt class="literal">Red::Blue</tt> package has nothing to do withany <tt class="literal">Red</tt> or <tt class="literal">Blue</tt> packages that might happen to exist. That is, arelationship between <tt class="literal">Red::Blue</tt> and <tt class="literal">Red</tt> or <tt class="literal">Blue</tt> may havemeaning to the person writing or using the program, but it meansnothing to Perl. (Well, other than the fact that, in the currentimplementation, the symbol table <tt class="literal">Red::Blue</tt> happens to be stored inthe symbol table <tt class="literal">Red</tt>. But the Perl language makes no use of thatdirectly.)</p><p>For this reason, every <tt class="literal">package</tt> declaration must declare a completepackage name. No package name ever assumes any kind of implied"prefix", even if (seemingly) declared within the scope of some otherpackage declaration.</p><p><a name="INDEX-2214"></a><a name="INDEX-2215"></a><a name="INDEX-2216"></a>Only identifiers (names starting with letters or an underscore) arestored in a package's symbol table. All other symbols are kept in the<tt class="literal">main</tt> package, including all the nonalphabeticvariables, like <tt class="literal">$!</tt>, <tt class="literal">$?</tt>, and<tt class="literal">$_</tt>. In addition, when unqualified, theidentifiers <tt class="literal">STDIN</tt>, <tt class="literal">STDOUT</tt>,<tt class="literal">STDERR</tt>, <tt class="literal">ARGV</tt>,<tt class="literal">ARGVOUT</tt>, <tt class="literal">ENV</tt>,<tt class="literal">INC</tt>, and <tt class="literal">SIG</tt> are forced to be inpackage <tt class="literal">main</tt>, even when used for other purposesthan their built-in ones. Don't name your package<tt class="literal">m</tt>, <tt class="literal">s</tt>, <tt class="literal">y</tt>,<tt class="literal">tr</tt>, <tt class="literal">q</tt>, <tt class="literal">qq</tt>,<tt class="literal">qr</tt>, <tt class="literal">qw</tt>, or <tt class="literal">qx</tt>unless you're looking for a lot of trouble. For instance, you won'tbe able to use the qualified form of an identifier as a filehandlebecause it will be interpreted instead as a pattern match, asubstitution, or a transliteration.</p><p><a name="INDEX-2217"></a>Long ago, variables beginning with an underscore were forced into the<tt class="literal">main</tt> package, but we decided it was more useful forpackage writers to be able to use a leading underscore to indicatesemi-private identifiers meant for internal use by that package only.(Truly private variables can be declared as file-scoped lexicals, butthat works best when the package and module have a one-to-onerelationship, which is common but not required.)</p><p><a name="INDEX-2218"></a>The <tt class="literal">%SIG</tt> hash (which is for trapping signals; see<a href="ch16_01.htm">Chapter 16, "Interprocess Communication"</a>) is alsospecial. If you define a signal handler as a string, it's assumed torefer to a subroutine in the <tt class="literal">main</tt> package unlessanother package name is explicitly used. Use a fully qualified signalhandler name if you want to specify a particular package, or avoidstrings entirely by assigning a typeglob or a function referenceinstead:<blockquote><pre class="programlisting">$SIG{QUIT} = "Pkg::quit_catcher"; # fully qualified handler name$SIG{QUIT} = "quit_catcher"; # implies "main::quit_catcher"$SIG{QUIT} = *quit_catcher; # forces current package's sub$SIG{QUIT} = \&quit_catcher; # forces current package's sub$SIG{QUIT} = sub { print "Caught SIGQUIT\n" }; # anonymous sub</pre></blockquote><a name="INDEX-2219"></a>The notion of "current package" is both a compile-time and run-timeconcept. Most variable name lookups happen at compile time, butrun-time lookups happen when symbolic references are dereferenced, andalso when new bits of code are parsed under <tt class="literal">eval</tt>.In particular, when you <tt class="literal">eval</tt> a string, Perl knowswhich package the <tt class="literal">eval</tt> was invoked in andpropagates that package inward when evaluating the string. (You canalways switch to a different package inside the<tt class="literal">eval</tt> string, of course, since an<tt class="literal">eval</tt> string counts as a block, just like a fileloaded in with <tt class="literal">do</tt>, <tt class="literal">require</tt>, or<tt class="literal">use</tt>.)</p><p>Alternatively, if an <tt class="literal">eval</tt> wants to find out what package it's in,the special symbol <tt class="literal">__PACKAGE__</tt> contains the current package name. Sinceyou can treat it as a string, you could use it in a symbolic referenceto access a package variable. But if you were doing that, chances areyou should have declared the variable with <tt class="literal">our</tt> instead so it couldbe accessed as if it were a lexical.</p><h2 class="sect1">10.1. Symbol Tables</h2><p><a name="INDEX-2220"></a><a name="INDEX-2221"></a><a name="INDEX-2222"></a><a name="INDEX-2223"></a>The contents of a package are collectively called a <em class="emphasis">symbol table</em>.Symbol tables are stored in a hash whose name is the same as thepackage, but with two colons appended. The <tt class="literal">main</tt> symbol table's nameis thus <tt class="literal">%main::</tt>. Since <tt class="literal">main</tt> also happens to be the defaultpackage, Perl provides <tt class="literal">%::</tt> as an abbreviation for <tt class="literal">%main::</tt>.</p><p>Likewise, the symbol table for the <tt class="literal">Red::Blue</tt> package is named<tt class="literal">%Red::Blue::</tt>. As it happens, the <tt class="literal">main</tt> symbol table contains allother top-level symbol tables, including itself, so <tt class="literal">%Red::Blue::</tt> isalso <tt class="literal">%main::Red::Blue::</tt>.</p><p><a name="INDEX-2224"></a><a name="INDEX-2225"></a>When we say that a symbol table "contains" another symbol table, wemean that it contains a reference to the other symbol table. Since<tt class="literal">main</tt> is the top-level package, it contains a reference to itself, withthe result that <tt class="literal">%main::</tt> is the same as <tt class="literal">%main::main::</tt>, and<tt class="literal">%main::main::main::</tt>, and so on, ad infinitum. It's important tocheck for this special case if you write code that traverses all symboltables.</p><p><a name="INDEX-2226"></a><a name="INDEX-2227"></a><a name="INDEX-2228"></a>Inside a symbol table's hash, each key/value pair matches a variablename to its value. The keys are the symbol identifiers, and thevalues are the corresponding typeglobs. So when you use the<tt class="literal">*</tt><em class="replaceable">NAME</em> typeglob notation,you're really just accessing a value in the hash that holds thecurrent package's symbol table. In fact, the following have (nearly)the same effect:<blockquote><pre class="programlisting">*sym = *main::variable;*sym = $main::{"variable"};</pre></blockquote>The first is more efficient because the <tt class="literal">main</tt> symbol table isaccessed at compile time. It will also create a new typeglob by thatname if none previously exists, whereas the second form will not.</p><p><a name="INDEX-2229"></a><a name="INDEX-2230"></a>Since a package is a hash, you can look up the keys of the package andget to all the variables of the package. Since the values of the hashare typeglobs, you can dereference them in several ways. Try this:<blockquote><pre class="programlisting">foreach $symname (sort keys %main::) { local *sym = $main::{$symname}; print "\$$symname is defined\n" if defined $sym; print "\@$symname is nonnull\n" if @sym; print "\%$symname is nonnull\n" if %sym;}</pre></blockquote><a name="INDEX-2231"></a>Since all packages are accessible (directly or indirectly) through the<tt class="literal">main</tt> package, you can write Perl code to visitevery package variable in your program. The Perl debugger doesprecisely that when you ask it to dump all your variables with the<tt class="literal">V</tt> command. Note that if you do this, you won't seevariables declared with <tt class="literal">my</tt> since those areindependent of packages, although you will see variables declared with<tt class="literal">our</tt>. See <a href="ch20_01.htm">Chapter 20, "The Perl Debugger"</a>.</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -