perlref.html

来自「perl教程」· HTML 代码 · 共 733 行 · 第 1/5 页

HTML
733
字号
Its disadvantage is that it won't create a new filehandle for you.
Its advantage is that you have less risk of clobbering more than
you want to with a typeglob assignment.  (It still conflates file
and directory handles, though.)  However, if you assign the incoming
value to a scalar instead of a typeglob as we do in the examples
below, there's no risk of that happening.</p>
<pre>
    <span class="variable">splutter</span><span class="operator">(</span><span class="variable">*STDOUT</span><span class="operator">);</span>          <span class="comment"># pass the whole glob</span>
    <span class="variable">splutter</span><span class="operator">(</span><span class="variable">*STDOUT</span><span class="operator">{</span><span class="string">IO</span><span class="operator">}</span><span class="operator">);</span>      <span class="comment"># pass both file and dir handles</span>
</pre>
<pre>
    <span class="keyword">sub</span><span class="variable"> splutter </span><span class="operator">{</span>
        <span class="keyword">my</span> <span class="variable">$fh</span> <span class="operator">=</span> <span class="keyword">shift</span><span class="operator">;</span>
        <span class="keyword">print</span> <span class="variable">$fh</span> <span class="string">"her um well a hmmm\n"</span><span class="operator">;</span>
    <span class="operator">}</span>
</pre>
<pre>
    <span class="variable">$rec</span> <span class="operator">=</span> <span class="variable">get_rec</span><span class="operator">(</span><span class="variable">*STDIN</span><span class="operator">);</span>     <span class="comment"># pass the whole glob</span>
    <span class="variable">$rec</span> <span class="operator">=</span> <span class="variable">get_rec</span><span class="operator">(</span><span class="variable">*STDIN</span><span class="operator">{</span><span class="string">IO</span><span class="operator">}</span><span class="operator">);</span> <span class="comment"># pass both file and dir handles</span>
</pre>
<pre>
    <span class="keyword">sub</span><span class="variable"> get_rec </span><span class="operator">{</span>
        <span class="keyword">my</span> <span class="variable">$fh</span> <span class="operator">=</span> <span class="keyword">shift</span><span class="operator">;</span>
        <span class="keyword">return</span> <span class="keyword">scalar</span> <span class="operator">&lt;</span><span class="variable">$fh</span><span class="operator">&gt;;</span>
    <span class="operator">}</span>
</pre>
</li>
</ol>
<p>
</p>
<h2><a name="using_references">Using References</a></h2>
<p>That's it for creating references.  By now you're probably dying to
know how to use references to get back to your long-lost data.  There
are several basic methods.</p>
<ol>
<li>
<p>Anywhere you'd put an identifier (or chain of identifiers) as part
of a variable or subroutine name, you can replace the identifier with
a simple scalar variable containing a reference of the correct type:</p>
<pre>
    <span class="variable">$bar</span> <span class="operator">=</span> <span class="variable">$$scalarref</span><span class="operator">;</span>
    <span class="keyword">push</span><span class="operator">(</span><span class="variable">@$arrayref</span><span class="operator">,</span> <span class="variable">$filename</span><span class="operator">);</span>
    <span class="variable">$$arrayref</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> <span class="string">"January"</span><span class="operator">;</span>
    <span class="variable">$$hashref</span><span class="operator">{</span><span class="string">"KEY"</span><span class="operator">}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>
    <span class="operator">&amp;</span><span class="variable">$coderef</span><span class="operator">(</span><span class="number">1</span><span class="operator">,</span><span class="number">2</span><span class="operator">,</span><span class="number">3</span><span class="operator">);</span>
    <span class="keyword">print</span> <span class="variable">$globref</span> <span class="string">"output\n"</span><span class="operator">;</span>
</pre>
<p>It's important to understand that we are specifically <em>not</em> dereferencing
<code>$arrayref[0]</code> or <code>$hashref{&quot;KEY&quot;}</code> there.  The dereference of the
scalar variable happens <em>before</em> it does any key lookups.  Anything more
complicated than a simple scalar variable must use methods 2 or 3 below.
However, a &quot;simple scalar&quot; includes an identifier that itself uses method
1 recursively.  Therefore, the following prints &quot;howdy&quot;.</p>
<pre>
    <span class="variable">$refrefref</span> <span class="operator">=</span> <span class="operator">\\\</span><span class="string">"howdy"</span><span class="operator">;</span>
    <span class="keyword">print</span> <span class="variable">$$$$refrefref</span><span class="operator">;</span>
</pre>
</li>
<li><strong></strong>

<p>Anywhere you'd put an identifier (or chain of identifiers) as part of a
variable or subroutine name, you can replace the identifier with a
BLOCK returning a reference of the correct type.  In other words, the
previous examples could be written like this:</p>
<pre>
    <span class="variable">$bar</span> <span class="operator">=</span> <span class="variable">$</span><span class="operator">{</span><span class="variable">$scalarref</span><span class="operator">}</span><span class="operator">;</span>
    <span class="keyword">push</span><span class="operator">(</span><span class="variable">@</span><span class="operator">{</span><span class="variable">$arrayref</span><span class="operator">}</span><span class="operator">,</span> <span class="variable">$filename</span><span class="operator">);</span>
    <span class="variable">$</span><span class="operator">{</span><span class="variable">$arrayref</span><span class="operator">}[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> <span class="string">"January"</span><span class="operator">;</span>
    <span class="variable">$</span><span class="operator">{</span><span class="variable">$hashref</span><span class="operator">}{</span><span class="string">"KEY"</span><span class="operator">}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>
    <span class="operator">&amp;{</span><span class="variable">$coderef</span><span class="operator">}(</span><span class="number">1</span><span class="operator">,</span><span class="number">2</span><span class="operator">,</span><span class="number">3</span><span class="operator">);</span>
    <span class="variable">$globref</span><span class="operator">-&gt;</span><span class="keyword">print</span><span class="operator">(</span><span class="string">"output\n"</span><span class="operator">);</span>  <span class="comment"># iff IO::Handle is loaded</span>
</pre>
<p>Admittedly, it's a little silly to use the curlies in this case, but
the BLOCK can contain any arbitrary expression, in particular,
subscripted expressions:</p>
<pre>
    <span class="operator">&amp;{</span> <span class="variable">$dispatch</span><span class="operator">{</span><span class="variable">$index</span><span class="operator">}</span> <span class="operator">}(</span><span class="number">1</span><span class="operator">,</span><span class="number">2</span><span class="operator">,</span><span class="number">3</span><span class="operator">);</span>      <span class="comment"># call correct routine</span>
</pre>
<p>Because of being able to omit the curlies for the simple case of <code>$$x</code>,
people often make the mistake of viewing the dereferencing symbols as
proper operators, and wonder about their precedence.  If they were,
though, you could use parentheses instead of braces.  That's not the case.
Consider the difference below; case 0 is a short-hand version of case 1,
<em>not</em> case 2:</p>
<pre>
    <span class="variable">$$hashref</span><span class="operator">{</span><span class="string">"KEY"</span><span class="operator">}</span>   <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>       <span class="comment"># CASE 0</span>
    <span class="variable">$</span><span class="operator">{</span><span class="variable">$hashref</span><span class="operator">}{</span><span class="string">"KEY"</span><span class="operator">}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>       <span class="comment"># CASE 1</span>
    <span class="variable">$</span><span class="operator">{</span><span class="variable">$hashref</span><span class="operator">{</span><span class="string">"KEY"</span><span class="operator">}}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>       <span class="comment"># CASE 2</span>
    <span class="variable">$</span><span class="operator">{</span><span class="variable">$hashref</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="string">"KEY"</span><span class="operator">}}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>     <span class="comment"># CASE 3</span>
</pre>
<p>Case 2 is also deceptive in that you're accessing a variable
called %hashref, not dereferencing through $hashref to the hash
it's presumably referencing.  That would be case 3.</p>
</li>
<li><strong><a name="item__3e_3e">  &gt;&gt;</a></strong>

<p>Subroutine calls and lookups of individual array elements arise often
enough that it gets cumbersome to use method 2.  As a form of
syntactic sugar, the examples for method 2 may be written:</p>
<pre>
    <span class="variable">$arrayref</span><span class="operator">-&gt;</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> <span class="string">"January"</span><span class="operator">;</span>   <span class="comment"># Array element</span>
    <span class="variable">$hashref</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="string">"KEY"</span><span class="operator">}</span> <span class="operator">=</span> <span class="string">"VALUE"</span><span class="operator">;</span>  <span class="comment"># Hash element</span>
    <span class="variable">$coderef</span><span class="operator">-&gt;(</span><span class="number">1</span><span class="operator">,</span><span class="number">2</span><span class="operator">,</span><span class="number">3</span><span class="operator">);</span>            <span class="comment"># Subroutine call</span>
</pre>
<p>The left side of the arrow can be any expression returning a reference,
including a previous dereference.  Note that <code>$array[$x]</code> is <em>not</em> the
same thing as <code>$array-&gt;[$x]</code> here:</p>
<pre>
    <span class="variable">$array</span><span class="operator">[</span><span class="variable">$x</span><span class="operator">]</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="string">"foo"</span><span class="operator">}</span><span class="operator">-&gt;</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> <span class="string">"January"</span><span class="operator">;</span>
</pre>
<p>This is one of the cases we mentioned earlier in which references could
spring into existence when in an lvalue context.  Before this
statement, <code>$array[$x]</code> may have been undefined.  If so, it's
automatically defined with a hash reference so that we can look up
<code>{&quot;foo&quot;}</code> in it.  Likewise <code>$array[$x]-&gt;{&quot;foo&quot;}</code> will automatically get
defined with an array reference so that we can look up <code>[0]</code> in it.
This process is called <em>autovivification</em>.</p>
<p>One more thing here.  The arrow is optional <em>between</em> brackets
subscripts, so you can shrink the above down to</p>
<pre>
    <span class="variable">$array</span><span class="operator">[</span><span class="variable">$x</span><span class="operator">]</span><span class="operator">{</span><span class="string">"foo"</span><span class="operator">}</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span> <span class="operator">=</span> <span class="string">"January"</span><span class="operator">;</span>
</pre>
<p>Which, in the degenerate case of using only ordinary arrays, gives you
multidimensional arrays just like C's:</p>
<pre>
    <span class="variable">$score</span><span class="operator">[</span><span class="variable">$x</span><span class="operator">][</span><span class="variable">$y</span><span class="operator">][</span><span class="variable">$z</span><span class="operator">]</span> <span class="operator">+=</span> <span class="number">42</span><span class="operator">;</span>
</pre>
<p>Well, okay, not entirely like C's arrays, actually.  C doesn't know how
to grow its arrays on demand.  Perl does.</p>
</li>
<li><strong></strong>

<p>If a reference happens to be a reference to an object, then there are
probably methods to access the things referred to, and you should probably
stick to those methods unless you're in the class package that defines the
object's methods.  In other words, be nice, and don't violate the object's
encapsulation without a very good reason.  Perl does not enforce
encapsulation.  We are not totalitarians here.  We do expect some basic
civility though.</p>
</li>
</ol>
<p>Using a string or number as a reference produces a symbolic reference,
as explained above.  Using a reference as a number produces an
integer representing its storage location in memory.  The only
useful thing to be done with this is to compare two references
numerically to see whether they refer to the same location.</p>
<pre>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?