📄 ch08_05.htm
字号:
<html><head><title>Braces, Brackets, and Quoting (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Braces, Brackets, and Quoting"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch08_04.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch08_01.htm">Chapter 8: References</a></td><td align="right" valign="top" width="172"><a href="ch09_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">8.5. Braces, Brackets, and Quoting</h2><p><a name="INDEX-2052"></a><a name="INDEX-2053"></a><a name="INDEX-2054"></a><a name="INDEX-2055"></a>In the previous section, we pointed out that <tt class="literal">${identifier}</tt> is nottreated as a symbolic reference. You might wonder how this interactswith reserved words, and the short answer is that it doesn't. Despitethe fact that <tt class="literal">push</tt> is a reserved word, these two statements print "<tt class="literal">pop on over</tt>":<blockquote><pre class="programlisting">$push = "pop on ";print "${push}over";</pre></blockquote>The reason is that, historically, this use of braces is how Unixshells have isolated a variable name from subsequent alphanumerictext that would otherwise be interpreted as part of the name. It'show many people expect variable interpolation to work, so we made itwork the same way in Perl. But with Perl, the notion extends furtherand applies to any braces used in generating references, whether ornot they're inside quotes. This means that:<blockquote><pre class="programlisting">print ${push} . 'over';</pre></blockquote>or even (since spaces never matter):<blockquote><pre class="programlisting">print ${ push } . 'over';</pre></blockquote>both print "<tt class="literal">pop on over</tt>", even though the braces areoutside of double quotes. The same rule applies to any identifier used for subscripting a hash. So, instead of writing:<blockquote><pre class="programlisting">$hash{ "aaa" }{ "bbb" }{ "ccc" }</pre></blockquote>you can just write:<blockquote><pre class="programlisting">$hash{ aaa }{ bbb }{ ccc }</pre></blockquote>or:<blockquote><pre class="programlisting">$hash{aaa}{bbb}{ccc}</pre></blockquote>and not worry about whether the subscripts are reserved words. So this:<blockquote><pre class="programlisting">$hash{ shift }</pre></blockquote>is interpreted as <tt class="literal">$hash{"shift"}</tt>. You can force interpretation asa reserved word by adding anything that makes it more than a mereidentifier:<blockquote><pre class="programlisting">$hash{ shift() }$hash{ +shift }$hash{ shift @_ }</pre></blockquote></p><h3 class="sect2">8.5.1. References Don't Work as Hash Keys</h3><a name="INDEX-2056"></a><a name="INDEX-2057"></a><p>Hash keys are stored internally as strings.<a href="#FOOTNOTE-8">[8]</a> If you try to store a reference as a key in ahash, the key value will be converted into a string:<blockquote><pre class="programlisting">$x{ \$a } = $a;($key, $value) = each %x;print $$key; # WRONG</pre></blockquote><a name="INDEX-2058"></a><a name="INDEX-2059"></a></p><blockquote class="footnote"><a name="FOOTNOTE-8"></a><p>[8] They're alsostored <em class="emphasis">externally</em> as strings, such as when you put them into a DBMfile. In fact, DBM files <em class="emphasis">require</em> that their keys (and values) bestrings.</p></blockquote><p>We mentioned earlier that you can't convert a string back to a hardreference. So if you try to dereference <tt class="literal">$key</tt>, which contains amere string, it won't return a hard dereference, but rather a symbolicdereference--and since you probably don't have a variable named<tt class="literal">SCALAR(0x1fc0e)</tt>, you won't accomplish what you're attempting. Youmight want to do something more like:<blockquote><pre class="programlisting">$r = \@a;$x{ $r } = $r;</pre></blockquote>Then at least you can use the hash <em class="emphasis">value</em>, which will be a hardreference, instead of the key, which won't.</p><p>Although you can't store a reference as a key, if (as in the earlierexample) you use a hard reference in a string context, it <em class="emphasis">is</em>guaranteed to produce a unique string, since the address of thereference is included as part of the resulting string. So you can infact use a reference as a unique hash key. You just can't dereferenceit later.</p><p><a name="INDEX-2060"></a>There is one special kind of hash in which you <em class="emphasis">are</em> able to usereferences as keys. Through the magic<a href="#FOOTNOTE-9">[9]</a> of the <tt class="literal">Tie::RefHash</tt>module bundled with Perl, the thing we just said you couldn't do, youcan do:<blockquote><pre class="programlisting">use Tie::RefHash;tie my %h, 'Tie::RefHash';%h = ( ["this", "here"] => "at home", ["that", "there"] => "elsewhere",);while ( my($keyref, $value) = each %h ) { print "@$keyref is $value\n";}</pre></blockquote>In fact, by tying different implementations to the built-in types, youcan make scalars, hashes, and arrays behave in many of the ways we've said youcan't. That'll show us! Stupid authors...</p><blockquote class="footnote"><a name="FOOTNOTE-9"></a><p>[9]Yes, that <em class="emphasis">is</em> atechnical term, as you'll notice if you muddle through the <em class="filename">mg.c</em> filein the Perl source distribution.</p></blockquote><p>For more about tying, see <a href="ch14_01.htm">Chapter 14, "Tied Variables"</a>.</p><a name="ch08-sect-garbage"></a><h3 class="sect2">8.5.2. Garbage Collection, Circular References, and Weak References</h3><a name="INDEX-2061"></a><a name="INDEX-2062"></a><a name="INDEX-2063"></a><a name="INDEX-2064"></a><a name="INDEX-2065"></a><a name="INDEX-2066"></a><a name="INDEX-2067"></a><a name="INDEX-2068"></a><p>High-level languages typically allow programmers not to worry aboutdeallocating memory when they're done using it. This automaticreclamation process is known as <em class="emphasis">garbage collection</em>. For mostpurposes, Perl uses a fast and simple reference-based garbagecollector.</p><p>When a block is exited, its locally scoped variables are normallyfreed up, but it is possible to hide your garbage so that Perl'sgarbage collector can't find it. One serious concern is thatunreachable memory with a nonzero reference count will normally notget freed. Therefore, circular references are a bad idea:<blockquote><pre class="programlisting">{ # make $a and $b point to each other my ($a, $b); $a = \$b; $b = \$a;}</pre></blockquote>or more simply:<blockquote><pre class="programlisting">{ # make $a point to itself my $a; $a = \$a;}</pre></blockquote>Even though <tt class="literal">$a</tt> should be deallocated at the end of the block, itisn't. When building recursive data structures, you'll have to break(or weaken; see below) the self-reference yourself if you want toreclaim the memory before your program (or thread) exits. (Upon exit,the memory will be reclaimed for you automatically via a costlybut complete mark-and-sweep garbage collection.) If the data structureis an object, you can use a <tt class="literal">DESTROY</tt> method to break the referenceautomatically; see "Garbage Collection with DESTROY Methods" in<a href="ch12_01.htm">Chapter 12, "Objects"</a>.</p><p>A similar situation can occur with <em class="emphasis">caches</em>--repositories of datadesigned for faster-than-normal retrieval. Outside the cache, thereare references to data inside the cache. The problem occurs when allof those references are deleted, but the cache data with its internalreference remains. The existence of any reference prevents thereferent from being reclaimed by Perl, even though we want cache datato disappear as soon as it's no longer needed. As with circularreferences, we want a reference that doesn't affect the referencecount, and therefore doesn't delay garbage collection.</p><p><em class="emphasis">Weak references</em> solve the problems caused by circular referencesand cache data by allowing you to "weaken" any reference; that is,make it not affect the reference count. When the last nonweakreference to an object is deleted, the object is destroyed and all theweak references to the object are automatically freed.</p><p>To use this feature, you need the <tt class="literal">WeakRef</tt> package from CPAN, whichcontains additional documentation. Weak references are anexperimental feature. But hey, somebody's gotta be the guinea pig.</p><!-- 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="ch08_04.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="ch09_01.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">8.4. Symbolic References</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">9. Data Structures</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 + -