⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch08_03.htm

📁 编程珍珠,里面很多好用的代码,大家可以参考学习呵呵,
💻 HTM
📖 第 1 页 / 共 3 页
字号:
* % &amp;</tt>) effectively bind more tightly than braces orbrackets.<a href="#FOOTNOTE-5">[5]</a> Therefore, it is<tt class="literal">$$listref</tt> and not <tt class="literal">$listref[2]</tt>that is taken to be areferenceto an array. If you want the C behavior, either you have to write<tt class="literal">${$listref[2]}</tt>to force the <tt class="literal">$listref[2]</tt> to get evaluated beforethe leading <tt class="literal">$</tt> dereferencer, or you have to use the<tt class="literal">-&gt;</tt> notation:<blockquote><pre class="programlisting">$listref[2]-&gt;[$greeting] = "hello";</pre></blockquote></p><blockquote class="footnote"><a name="FOOTNOTE-5"></a><p>[5] But not because of operator precedence.  Thefunny characters in Perl are not operators in that sense.  Perl'sgrammar simply prohibits anything more complicated than a simplevariable or block from following the initial funny character, forvarious funny reasons.</p></blockquote><h3 class="sect2">8.3.4. Using Object Methods</h3><a name="INDEX-2016"></a><a name="INDEX-2017"></a><a name="INDEX-2018"></a><a name="INDEX-2019"></a><p>If a reference happens to be a reference to an object, then the classthat defines that object probably provides methods to access theinnards of the object, and you should generally stick to those methodsif you're merely using the class (as opposed to implementing it).  In otherwords, be nice, and don't treat an object like a regular reference,even though Perl lets you when you really need to.  Perl does notenforce encapsulation.  We are not totalitarians here.  We do expectsome basic civility, however.</p><p>In return for this civility, you get complete orthogonality betweenobjects and data structures.  Any data structure can behave as an objectwhen you want it to.  Or not, when you don't.</p><a name="ch08-sect-pseudo"></a><h3 class="sect2">8.3.5. Pseudohashes</h3><a name="INDEX-2020"></a><p>A <em class="emphasis">pseudohash</em> is any reference to an array whose first element is areference to a hash.  You can treat the pseudohash reference as either anarray reference (as you would expect) or a hash reference (as you might not expect).  Here's an example of a pseudohash:<blockquote><pre class="programlisting">$john = [ {age =&gt; 1, eyes =&gt; 2, weight =&gt; 3}, 47, "brown", 186 ];</pre></blockquote>The underlying hash in <tt class="literal">$john-&gt;[0]</tt> defines the names (<tt class="literal">"age"</tt>, <tt class="literal">"eyes"</tt>,<tt class="literal">"weight"</tt>) of the array elements that follow (<tt class="literal">47</tt>, <tt class="literal">"brown"</tt>, <tt class="literal">186</tt>).  Nowyou can access an element with both hash and array notations:<blockquote><pre class="programlisting">$john-&gt;{weight}             # Treats $john as a hashref$john-&gt;[3]                  # Treats $john as an arrayref</pre></blockquote>Pseudohash magic is not deep; it only knows one "trick": how to turn a hash dereference into an array dereference. When adding another element to apseudohash, you have to explicitly tell the underlying mapping hash where the elementwill reside before you can use the hash notation:<blockquote><pre class="programlisting">$john-&gt;[0]{height} = 4;     # height is to be element 4$john-&gt;{height} = "tall";   # Or $john-&gt;[4] = "tall"</pre></blockquote>Perl raises an exception if you try to delete a key from a pseudohash,although you can always delete keys from the mapping hash.  Perlalso raises an exception if you try to access a nonexistent key,where "existence" means presence in the mapping hash:<blockquote><pre class="programlisting">delete $john-&gt;[0]{height};  # Deletes from the underlying hash only$john-&gt;{height};            # This now raises an exception$john-&gt;[4];                 # Still prints "tall"</pre></blockquote>Don't try to splice the array unless you know what you'redoing.  If the array elements move around, the mapping hash valueswill still refer to the <em class="emphasis">old</em> element positions, unless you changethose explicitly, too.  Pseudohash magic is not deep.</p><p>To avoid inconsistencies, you can use the <tt class="literal">fields::phash</tt> functionprovided by the <tt class="literal">use fields</tt> pragma to create a pseudohash:<blockquote><pre class="programlisting">use fields;$ph = fields::phash(age =&gt; 47, eyes =&gt; "brown", weight =&gt; 186);print $ph-&gt;{age};</pre></blockquote>There are two ways to check for the existence of a key in apseudohash.  The first is to use <tt class="literal">exists</tt>, which checks whether thegiven field has ever been set.  It acts this way to match the behaviorof a real hash.  For instance:<blockquote><pre class="programlisting">use fields;$ph= fields::phash([qw(age eyes brown)], [47]);$ph-&gt;{eyes} = undef;print exists $ph-&gt;{age};     # True, 'age' was set in declaration.print exists $ph-&gt;{weight};  # False, 'weight' has not been used.print exists $ph-&gt;{eyes};    # True, your 'eyes' have been touched.</pre></blockquote>The second way is to use <tt class="literal">exists</tt> on the mapping hash sitting in thefirst array element.  This checks whether the given key is a validfield for that pseudohash:<blockquote><pre class="programlisting">print exists $ph-&gt;[0]{age};   # True, 'age' is a valid fieldprint exists $ph-&gt;[0]{name};  # False, 'name' can't be used</pre></blockquote>Unlike what happens in a real hash, calling <tt class="literal">delete</tt> on a pseudohashelement deletes only the array value corresponding to the key, not thereal key in the mapping hash.  To delete the key, you have toexplicitly delete it from the mapping hash.  Once you do that, you mayno longer use that key name as a pseudohash subscript:<blockquote><pre class="programlisting">print delete $ph-&gt;{age};     # Removes and returns $ph-&gt;[1], 47print exists $ph-&gt;{age};     # Now falseprint exists $ph-&gt;[0]{age};  # True, 'age' key still usableprint delete $ph-&gt;[0]{age};  # Now 'age' key is goneprint $ph-&gt;{age};            # Run-time exception</pre></blockquote>You've probably begun to wonder what could possibly have motivatedthis masquerade of arrays prancing about in hashes' clothing.  Arraysprovide faster lookups and more efficient storage, while hashes offer theconvenience of naming (instead of numbering) your data;pseudohashes provide the best of both worlds.  But it's not until youconsider Perl's compilation phase that the greatest benefit becomesapparent.  With the help of a pragma or two, the compiler can verifyproper access to valid fields, so you can find out about nonexistentsubscripts (or spelling errors) before your program starts to run.</p><p>Pseudohashes' properties of speed, efficiency, and compile-timeaccess checking (you might even think of it as type safety) areespecially handy for creating efficient and robust class modules.See the discussion of the <tt class="literal">use fields</tt> pragma in <a href="ch12_01.htm">Chapter 12, "Objects"</a> and <a href="ch31_01.htm">Chapter 31, "Pragmatic Modules"</a>.</p><p>Pseudohashes are a new and relatively experimental feature; as such,the underlying implementation may well change in the future.  Toprotect yourself from such changes, always go through the <tt class="literal">fields</tt>module's documented interface via its <tt class="literal">phash</tt> and <tt class="literal">new</tt> functions.</p><a name="ch08-sect-tricks"></a><h3 class="sect2">8.3.6. Other Tricks You Can Do with Hard References</h3><p>As mentioned earlier, the backslash operator is usually usedon a single referent to generate a single reference, but it doesn't haveto be.  When used on a list of referents, it produces a list ofcorresponding references.  The second line of the following example does the same thing as the first line, since the backslashis automatically distributed throughout the whole list.<blockquote><pre class="programlisting">@reflist = (\$s, \@a, \%h, \&amp;f);     # List of four references@reflist = \($s,  @a   %h,  &amp;f);     # Same thing</pre></blockquote>If a parenthesized list contains exactly one array or hash, then allof its values are interpolated and references to each returned:<blockquote><pre class="programlisting">@reflist = \(@x);                    # Interpolate array, then get refs@reflist = map { \$_ } @x;           # Same thing</pre></blockquote>This also occurs when there are internal parentheses:<blockquote><pre class="programlisting">@reflist = \(@x, (@y));              # But only single aggregates expand@reflist = (\@x, map { \$_ } @y);    # Same thing</pre></blockquote>If you try this with a hash, the result will contain references tothe values (as you'd expect), but references to <em class="emphasis">copies</em> of the keys(as you might not expect).</p><p>Since array and hash slices are really just lists, you can backslash aslice of either of these to get a list of references.  Each of thenext three lines does exactly the same thing:<blockquote><pre class="programlisting">@envrefs = \@ENV{'HOME', 'TERM'};         # Backslashing a slice@envrefs = \( $ENV{HOME},  $ENV{TERM} );  # Backslashing a list@envrefs = ( \$ENV{HOME}, \$ENV{TERM} );  # A list of two references</pre></blockquote>Since functions can return lists, you can apply a backslash to them.If you have more than one function to call, first interpolate eachfunction's return values into a larger list and then backslash thewhole thing:<blockquote><pre class="programlisting">@reflist = \fx();@reflist = map { \$_ } fx();                # Same thing@reflist = \( fx(), fy(), fz() );@reflist = ( \fx(), \fy(), \fz() );         # Same thing@reflist = map { \$_ } fx(), fy(), fz();    # Same thing</pre></blockquote><a name="INDEX-2021"></a>The backslash operator always supplies a list context to its operand,so those functions are all called in list context.  If the backslashis itself in scalar context, you'll end up with a reference to thelast value of the list returned by the function:<blockquote><pre class="programlisting">@reflist = \localtime();      # Ref to each of nine time elements$lastref = \localtime();      # Ref to whether it's daylight savings time</pre></blockquote>In this regard, the backslash behaves like the named Perl listoperators, such as <tt class="literal">print</tt>, <tt class="literal">reverse</tt>, and <tt class="literal">sort</tt>, which alwayssupply a list context on their right no matter what might be happeningon their left.  As with named list operators, use an explicit<tt class="literal">scalar</tt> to force what follows into scalar context:<blockquote><pre class="programlisting">$dateref = \scalar localtime();    # \"Sat Jul 16 11:42:18 2000"</pre></blockquote><a name="INDEX-2022"></a></p><p>You can use the <tt class="literal">ref</tt> operator to determine what a reference ispointing to.  Think of <tt class="literal">ref</tt> as a "typeof" operator that returns trueif its argument is a reference and false otherwise.  The valuereturned depends on the type of thing referenced. Built-in typesinclude <tt class="literal">SCALAR</tt>, <tt class="literal">ARRAY</tt>, <tt class="literal">HASH</tt>, <tt class="literal">CODE</tt>, <tt class="literal">GLOB</tt>, <tt class="literal">REF</tt>,<tt class="literal">LVALUE</tt>, <tt class="literal">IO</tt>, <tt class="literal">IO::Handle</tt>, and <tt class="literal">Regexp</tt>.  Here, we useit to check subroutine arguments:<blockquote><pre class="programlisting">sub sum {    my $arrayref = shift;    warn "Not an array reference" if ref($arrayref) ne "ARRAY";    return eval join("+", @$arrayref);}</pre></blockquote><a name="INDEX-2023"></a><a name="INDEX-2024"></a></p><p>If you use a hard reference in a string context, it'll be converted toa string containing both the type and the address:<tt class="literal">SCALAR(0x1fc0e)</tt>. (The reverse conversion cannot be done, sincereference count information is lost during stringification--and alsobecause it would be dangerous to let programs access a memory addressnamed by an arbitrary string.)</p><p><a name="INDEX-2025"></a><a name="INDEX-2026"></a><a name="INDEX-2027"></a>You can use the <tt class="literal">bless</tt> operator to associate a referent with apackage functioning as an object class.  When you do this, <tt class="literal">ref</tt>returns the class name instead of the internal type.  An objectreference used in a string context returns a string with the externaland internal types, and the address in memory:<tt class="literal">MyType=HASH(0x20d10)</tt> or <tt class="literal">IO::Handle=IO(0x186904)</tt>.  See <a href="ch12_01.htm">Chapter 12, "Objects"</a> for more details about objects.</p><p><a name="INDEX-2028"></a><a name="INDEX-2029"></a>Since the way in which you dereference something always indicates whatsort of referent you're looking for, a typeglob can be used the sameway a reference can, despite the fact that a typeglob containsmultiple referents of various types.  So <tt class="literal">${*main::foo}</tt> and <tt class="literal">${\$main::foo}</tt>both access the same scalar variable, although the latter is moreefficient.</p><p><a name="INDEX-2030"></a>Here's a trick for interpolating the return value of a subroutine callinto a string:<blockquote><pre class="programlisting">print "My sub returned @{[ mysub(1,2,3) ]} that time.\n";</pre></blockquote>It works like this.  At compile time, when the <tt class="literal">@{...}</tt> is seenwithin the double-quoted string, it's parsed as a block that returnsa reference.  Within the block, there are square brackets thatcreate a reference to an anonymous array from whatever is in thebrackets.  So at run time, <tt class="literal">mysub(1,2,3)</tt> is called in list context,and the results are loaded into an anonymous array, a reference towhich is then returned within the block.  That array reference isthen immediately dereferenced by the surrounding <tt class="literal">@{...}</tt>, and thearray value is interpolated into the double-quoted string just asan ordinary array would be.  This chicanery is also useful forarbitrary expressions, such as:

⌨️ 快捷键说明

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