📄 ch10_01.htm
字号:
<p>Earlier we said that only identifiers are stored in packages other than<tt class="literal">main</tt>. That was a bit of a fib: you can use any string you want as thekey in a symbol table hash--it's just that it wouldn't be valid Perl ifyou tried to use a non-identifier directly:<blockquote><pre class="programlisting">$!@#$% = 0; # WRONG, syntax error.${'!@#$%'} = 1; # Ok, though unqualified.${'main::!@#$%'} = 2; # Can qualify within the string.print ${ $main::{'!@#$%'} } # Ok, prints 2!</pre></blockquote><a name="INDEX-2232"></a>Assignment to a typeglob performs an aliasing operation; that is,<blockquote><pre class="programlisting">*dick = *richard;</pre></blockquote>causes variables, subroutines, formats, and file and directory handlesaccessible via the identifier <tt class="literal">richard</tt> to also beaccessible via the symbol <tt class="literal">dick</tt>. If you want toalias only a particular variable or subroutine, assign a referenceinstead:<blockquote><pre class="programlisting">*dick = \$richard;</pre></blockquote>That makes <tt class="literal">$richard</tt> and <tt class="literal">$dick</tt> the same variable, but leaves<tt class="literal">@richard</tt> and <tt class="literal">@dick</tt> as separate arrays. Tricky, eh?</p><p><a name="INDEX-2233"></a>This is how the <tt class="literal">Exporter</tt> works when importing symbols from onepackage to another. For example:<blockquote><pre class="programlisting">*SomePack::dick = \&OtherPack::richard;</pre></blockquote>imports the <tt class="literal">&richard</tt> function from package <tt class="literal">OtherPack</tt> into<tt class="literal">SomePack</tt>, making it available as the <tt class="literal">&dick</tt> function. (The<tt class="literal">Exporter</tt> module is described in the next chapter.) If youprecede the assignment with a <tt class="literal">local</tt>, the aliasing will only last aslong as the current dynamic scope.</p><p><a name="INDEX-2234"></a><a name="INDEX-2235"></a>This mechanism may be used to retrieve a reference from a subroutine,making the referent available as the appropriate data type:<blockquote><pre class="programlisting">*units = populate() ; # Assign \%newhash to the typeglobprint $units{kg}; # Prints 70; no dereferencing needed!sub populate { my %newhash = (km => 10, kg => 70); return \%newhash;}</pre></blockquote>Likewise, you can pass a reference into a subroutine and use itwithout dereferencing:<blockquote><pre class="programlisting">%units = (miles => 6, stones => 11); fillerup( \%units ); # Pass in a referenceprint $units{quarts}; # Prints 4sub fillerup { local *hashsym = shift; # Assign \%units to the typeglob $hashsym{quarts} = 4; # Affects %units; no dereferencing needed!}</pre></blockquote>These are tricky ways to pass around references cheaply when you don'twant to have to explicitly dereference them. Note that bothtechniques only work with package variables; they would not haveworked had we declared <tt class="literal">%units</tt> with<tt class="literal">my</tt>.</p><p><a name="INDEX-2236"></a><a name="INDEX-2237"></a><a name="INDEX-2238"></a><a name="INDEX-2239"></a>Another use of symbol tables is for making "constant" scalars:<blockquote><pre class="programlisting">*PI = \3.14159265358979;</pre></blockquote><a name="INDEX-2240"></a><a name="INDEX-2241"></a>Now you cannot alter <tt class="literal">$PI</tt>, which is probably a goodthing, all in all. This isn't the same as a constant subroutine,which is optimized at compile time. A constant subroutine is oneprototyped to take no arguments and to return a constant expression;see <a href="ch06_04.htm#ch06-sect-icf">Section 10.4.1, "Inlining Constant Functions"</a> in <a href="ch06_01.htm">Chapter 6, "Subroutines"</a>, for details. The <tt class="literal">useconstant</tt> pragma (see <a href="ch31_01.htm">Chapter 31, "Pragmatic Modules"</a>) is a convenient shorthand:<blockquote><pre class="programlisting">use constant PI => 3.14159;</pre></blockquote>Under the hood, this uses the subroutine slot of<tt class="literal">*PI</tt>, instead of the scalar slot used earlier. It'sequivalent to the more compact (but less readable):<blockquote><pre class="programlisting">*PI = sub () { 3.14159 };</pre></blockquote>That's a handy idiom to know anyway--assigning a <tt class="literal">sub{}</tt> to a typeglob is the way to give a name to an anonymoussubroutine at run time.</p><p><a name="INDEX-2242"></a><a name="INDEX-2243"></a>Assigning a typeglob reference to another typeglob (<tt class="literal">*sym =\*oldvar</tt>) is the same as assigning the entire typeglob,because Perl automatically dereferences the typeglob reference foryou. And when you set a typeglob to a simple string, you get theentire typeglob named by that string, because Perl looks up the stringin the current symbol table. The following are all equivalent to oneanother, though the first two compute the symbol table entry atcompile time, while the last two do so at run time:<blockquote><pre class="programlisting">*sym = *oldvar;*sym = \*oldvar; # autodereference*sym = *{"oldvar"}; # explicit symbol table lookup*sym = "oldvar"; # implicit symbol table lookup</pre></blockquote>When you perform any of the following assignments, you're replacing justone of the references within the typeglob:<blockquote><pre class="programlisting">*sym = \$frodo;*sym = \@sam;*sym = \%merry;*sym = \&pippin;</pre></blockquote>If you think about it sideways, the typeglob itself can be viewed as akind of hash, with entries for the different variable types in it. Inthis case, the keys are fixed, since a typeglob can contain exactly onescalar, one array, one hash, and so on. But you can pull out theindividual references, like this:<blockquote><pre class="programlisting">*pkg::sym{SCALAR} # same as \$pkg::sym*pkg::sym{ARRAY} # same as \@pkg::sym*pkg::sym{HASH} # same as \%pkg::sym*pkg::sym{CODE} # same as \&pkg::sym*pkg::sym{GLOB} # same as \*pkg::sym*pkg::sym{IO} # internal file/dir handle, no direct equivalent*pkg::sym{NAME} # "sym" (not a reference)*pkg::sym{PACKAGE} # "pkg" (not a reference)</pre></blockquote>You can say <tt class="literal">*foo{PACKAGE}</tt> and<tt class="literal">*foo{NAME}</tt> to find out what name and package the<tt class="literal">*foo</tt> symbol table entry comes from. This may beuseful in a subroutine that is passed typeglobs as arguments:<blockquote><pre class="programlisting">sub identify_typeglob { my $glob = shift; print 'You gave me ', *{$glob}{PACKAGE}, '::', *{$glob}{NAME}, "\n";}identify_typeglob(*foo);identify_typeglob(*bar::glarch);</pre></blockquote>This prints:<blockquote><pre class="programlisting">You gave me main::fooYou gave me bar::glarch</pre></blockquote>The<tt class="literal">*foo{</tt><em class="replaceable">THING</em><tt class="literal">}</tt>notation can be used to obtain references to individual elements of<tt class="literal">*foo</tt>. See the section <a href="ch08_02.htm#ch08-sect-str">Section 10.2.5, "Symbol Table References"</a> in<a href="ch08_01.htm">Chapter 8, "References"</a> for details.</p><p>This syntax is primarily used to get at the internal filehandle ordirectory handle reference, because the other internal references arealready accessible in other ways. (The old<tt class="literal">*foo{FILEHANDLE}</tt> is still supported to mean<tt class="literal">*foo{IO}</tt>, but don't let its name fool you intothinking it can distinguish filehandles from directory handles.) Butwe thought we'd generalize it because it looks kind of pretty. Sortof. You probably don't need to remember all this unless you'replanning to write another Perl debugger.</p><a name="INDEX-2244"></a><a name="INDEX-2245"></a><a name="INDEX-2246"></a><a name="INDEX-2267"></a><!-- BOTTOM NAV BAR --><hr width="515" align="left"><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch09_07.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="index.htm"><img src="../gifs/txthome.gif" alt="Home" border="0"></a></td><td align="right" valign="top" width="172"><a href="ch10_02.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">9.7. Saving Data Structures</td><td align="center" valign="top" width="171"><a href="index/index.htm"><img src="../gifs/index.gif" alt="Book Index" border="0"></a></td><td align="right" valign="top" width="172">10.2. Autoloading</td></tr></table></div><hr width="515" align="left"><!-- LIBRARY NAV BAR --><img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p><font size="-1"><a href="copyrght.htm">Copyright © 2001</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"> <area shape="rect" coords="2,-1,79,99" href="../index.htm"><area shape="rect" coords="84,1,157,108" href="../perlnut/index.htm"><area shape="rect" coords="162,2,248,125" href="../prog/index.htm"><area shape="rect" coords="253,2,326,130" href="../advprog/index.htm"><area shape="rect" coords="332,1,407,112" href="../cookbook/index.htm"><area shape="rect" coords="414,2,523,103" href="../sysadmin/index.htm"></map><!-- END OF BODY --></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -