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

📄 ch06_04.htm

📁 编程珍珠,里面很多好用的代码,大家可以参考学习呵呵,
💻 HTM
📖 第 1 页 / 共 2 页
字号:
<blockquote><pre class="programlisting">sub try (&amp;$) {    my ($try, $catch) = @_;    eval { &amp;$try };    if ($@) {        local $_ = $@;        &amp;$catch;    }}sub catch (&amp;) { $_[0] }try {    die "phooey";}                   # not the end of the function call!catch {    /phooey/ and print "unphooey\n";};</pre></blockquote>This prints "<tt class="literal">unphooey</tt>".  What happens is that<tt class="literal">try</tt> is called with two arguments, the anonymousfunction <tt class="literal">{die "phooey";}</tt> and the returnvalue of the <tt class="literal">catch</tt> function, which in this case isnothing but its own argument, the entire block of yet anotheranonymous function.  Within <tt class="literal">try</tt>, the first functionargument is called while protected within an <tt class="literal">eval</tt>block to trap anything that blows up.  If something does blow up, thesecond function is called with a local version of the global<tt class="literal">$_</tt> variable set to the raisedexception.<a href="#FOOTNOTE-3">[3]</a> If this allsounds like pure gobbledygook, you'll have to read about<tt class="literal">die</tt> and <tt class="literal">eval</tt> in <a href="ch29_01.htm">Chapter 29, "Functions"</a>, and then go check out anonymousfunctions and closures in <a href="ch08_01.htm">Chapter 8, "References"</a>.  Onthe other hand, if it intrigues you, you might check out the<tt class="literal">Error</tt> module on CPAN, which uses this to implementelaborately structured exception handling with <tt class="literal">try</tt>,<tt class="literal">catch</tt>, <tt class="literal">except</tt>,<tt class="literal">otherwise</tt>, and <tt class="literal">finally</tt> clauses.</p><blockquote class="footnote"><a name="FOOTNOTE-3"></a><p>[3] Yes, there are still unresolved issueshaving to do with the visibility of <tt class="literal">@_</tt>.  We'reignoring that question for the moment.  But if we make<tt class="literal">@_</tt> lexically scoped someday, as already occurs inthe experimental threaded versions of Perl, those anonymoussubroutines can act like closures.</p></blockquote><p>Here's a reimplementation of the <tt class="literal">grep</tt> operator (the built-in oneis more efficient, of course):<blockquote><pre class="programlisting">sub mygrep (&amp;@) {    my $coderef = shift;    my @result;    foreach $_ (@_) {        push(@result, $_) if &amp;$coderef;    }    return @result;}</pre></blockquote>Some folks would prefer to see full alphanumeric prototypes.Alphanumerics have been intentionally left out of prototypes for theexpress purpose of someday adding named, formal parameters.  (Maybe.)The current mechanism's main goal is to let module writers enforce acertain amount of compile-time checking on module users.</p><a name="ch06-sect-icf"></a><h3 class="sect2">6.4.1. Inlining Constant Functions</h3><p><a name="INDEX-1862"></a><a name="INDEX-1863"></a><a name="INDEX-1864"></a>Functions prototyped with <tt class="literal">()</tt>, meaning that theytake no arguments at all, are parsed like the <tt class="literal">time</tt>built-in.  More interestingly, the compiler treats such functions aspotential candidates for inlining.  If the result of that function,after Perl's optimization and constant-folding pass, is either aconstant or a lexically scoped scalar with no other references, thenthat value will be used in place of calls to that function.  Callsmade using <tt class="literal">&amp;</tt><em class="replaceable">NAME</em> arenever inlined, however, just as they are not subject to any otherprototype effects.  (See the <tt class="literal">use constant</tt> pragma in<a href="ch31_01.htm">Chapter 31, "Pragmatic Modules"</a>, for an easy way todeclare such constants.)</p><p></p><p>Both version of these functions to compute <img src="figs/pi.gif"> will be inlinedby the compiler:<blockquote><pre class="programlisting">sub pi ()           { 3.14159 }             # Not exact, but closesub PI ()           { 4 * atan2(1, 1) }     # As good as it gets</pre></blockquote>In fact, all of the following functions are inlined because Perl candetermine everything at compile time:<blockquote><pre class="programlisting">sub FLAG_FOO ()     { 1 &lt;&lt; 8 }sub FLAG_BAR ()     { 1 &lt;&lt; 9 }sub FLAG_MASK ()    { FLAG_FOO | FLAG_BAR }sub OPT_GLARCH ()   { (0x1B58 &amp; FLAG_MASK) == 0 }sub GLARCH_VAL ()   {    if (OPT_GLARCH) { return 23 }    else            { return 42 }}sub N () { int(GLARCH_VAL) / 3 }BEGIN {                 # compiler runs this block at compile time    my $prod = 1;       # persistent, private variable    for (1 .. N) { $prod *= $_ }    sub NFACT () { $prod }}</pre></blockquote>In the last example, the <tt class="literal">NFACT</tt> function is inlined because it has avoid prototype and the variable it returns is not changed by thatfunction--and furthermore can't be changed by anyone else, since it'sin a lexical scope.  So the compiler replaces uses of <tt class="literal">NFACT</tt> withthat value, which was precomputed at compile time because of thesurrounding <tt class="literal">BEGIN</tt>.</p><p><a name="INDEX-1865"></a><a name="INDEX-1866"></a>If you redefine a subroutine that was eligible for inlining, you'llget a mandatory warning.  (You can use this warning to tell whetherthe compiler inlined a particular subroutine.)  The warning isconsidered severe enough not to be optional, because previouslycompiled invocations of the function will still use the old valueof the function.  If you need to redefine the subroutine, ensurethat it isn't inlined either by dropping the <tt class="literal">()</tt> prototype (whichchanges calling semantics, so beware) or by thwarting the inliningmechanism in some other way, such as:<blockquote><pre class="programlisting">sub not_inlined () {    return 23 if $$;}</pre></blockquote>See <a href="ch18_01.htm">Chapter 18, "Compiling"</a> for more about what happensduring the compilation and execution phases of your program'slife.</p><h3 class="sect2">6.4.2. Care with Prototypes</h3><p><a name="INDEX-1867"></a><a name="INDEX-1868"></a>It's probably best to put prototypes on new functions, not retrofitprototypes onto older ones.  These are context templates, not ANSIC prototypes, so you must be especially careful about silentlyimposing a different context.  Suppose, for example, you decidethat a function should take just one parameter, like this:<blockquote><pre class="programlisting">sub func ($) {    my $n = shift;    print "you gave me $n\n";}</pre></blockquote><a name="INDEX-1869"></a>That makes it a unary operator (like the <tt class="literal">rand</tt> built-in)and changes how the compiler determines the function's arguments.  With thenew prototype, the function consumes just one, scalar-contextargument instead of many arguments in list context.  If someone hasbeen calling it with an array or list expression, even if that arrayor list contained just a single element, where before it worked,now you've got something completely different:<blockquote><pre class="programlisting">func @foo;                  # counts @foo elementsfunc split /:/;             # counts number of fields returnedfunc "a", "b", "c";         # passes "a" only, discards "b" and "c"func("a", "b", "c");        # suddenly, a compiler error!</pre></blockquote>You've just supplied an implicit <tt class="literal">scalar</tt> in front of theargument list, which can be more than a bit surprising.  The old <tt class="literal">@foo</tt>that used to hold one thing doesn't get passed in.  Instead, 1 (thenumber of elements in <tt class="literal">@foo</tt>) is now passed to <tt class="literal">func</tt>.  And the<tt class="literal">split</tt>, being called in scalar context, scribbles all over your<tt class="literal">@_</tt> parameter list.  In the third example, because <tt class="literal">func</tt> has beenprototyped as a unary operator, only "<tt class="literal">a</tt>" is passed in; then thereturn value from <tt class="literal">func</tt> is discarded as the comma operator goes onto evaluate the next two items and return "<tt class="literal">c</tt>."  In the finalexample, the user now gets a syntax error at compile time on code thatused to compile and run just fine.</p><p>If you're writing new code and would like a unary operator thattakes only a scalar variable, not any old scalar expression, youcould prototype it to take a scalar <em class="emphasis">reference</em>:<blockquote><pre class="programlisting">sub func (\$) {    my $nref = shift;    print "you gave me $$nref\n";}</pre></blockquote>Now the compiler won't let anything by that doesn't start with adollar sign:<blockquote><pre class="programlisting">func @foo;              # compiler error, saw @, want $func split/:/;          # compiler error, saw function, want $func $s;                # this one is ok -- got real $ symbolfunc $a[3];             # and this onefunc $h{stuff}[-1];     # or even thisfunc 2+5;               # scalar expr still a compiler errorfunc ${ \(2+5) };       # ok, but is the cure worse than the disease?</pre></blockquote>If you aren't careful, you can get yourself into trouble withprototypes.  But if you are careful, you can do a lot of neat thingswith them.  This is all very powerful, of course, and should only beused in moderation to make the world a better place.</p><a name="INDEX-1870"></a><a name="INDEX-1871"></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="ch06_03.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="ch06_05.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">6.3. Passing 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">6.5. Subroutine Attributes</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 &copy; 2001</a> O'Reilly &amp; 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 + -