📄 ch06_02.htm
字号:
it things like this:<blockquote><pre class="programlisting">@newlist = upcase(@list1, @list2);@newlist = upcase( split /:/, $var );</pre></blockquote>Do not, however, be tempted to do this:<blockquote><pre class="programlisting">(@a, @b) = upcase(@list1, @list2); # WRONG</pre></blockquote>Why not? Because, like the flat incoming parameter list in <tt class="literal">@_</tt>, thereturn list is also flat. So this stores everything in <tt class="literal">@a</tt> andempties out <tt class="literal">@b</tt> by storing the null list there. See the later section <a href="ch06_03.htm#ch06-sect-pr">Section 6.3, "Passing References"</a> for alternatives.</p><h3 class="sect2">6.2.2. Error Indications</h3><p><a name="INDEX-1825"></a><a name="INDEX-1826"></a>If you want your function to return in such a way that the caller willrealize there's been an error, the most natural way to do this in Perlis to use a bare <tt class="literal">return</tt> statement without an argument. That waywhen the function is used in scalar context, the caller gets <tt class="literal">undef</tt>,and when used in list context, the caller gets a null list.</p><p><a name="INDEX-1827"></a>Under extraordinary circumstances, you might choose to raise anexception to indicate an error. Use this measure sparingly, though;otherwise, your whole program will be littered with exceptionhandlers. For example, failing to open a file in a genericfile-opening function is hardly an exceptional event. However,ignoring that failure might well be. The <tt class="literal">wantarray</tt> built-inreturns <tt class="literal">undef</tt> if your function was called in void context, so youcan tell if you're being ignored:<blockquote><pre class="programlisting">if ($something_went_awry) { return if defined wantarray; # good, not void context. die "Pay attention to my error, you danglesocket!!!\n";}</pre></blockquote></p><h3 class="sect2">6.2.3. Scoping Issues</h3><p><a name="INDEX-1828"></a><a name="INDEX-1829"></a><a name="INDEX-1830"></a>Subroutines may be called recursively because each call gets its ownargument array, even when the routine calls itself. If a subroutineis called using the <tt class="literal">&</tt> form, the argument list is optional. If the<tt class="literal">&</tt> is used but the argument list is omitted, something specialhappens: the <tt class="literal">@_</tt> array of the calling routine is suppliedimplicitly. This is an efficiency mechanism that new users may wishto avoid.<blockquote><pre class="programlisting">&foo(1,2,3); # pass three argumentsfoo(1,2,3); # the samefoo(); # pass a null list&foo(); # the same&foo; # foo() gets current args, like foo(@_), but faster!foo; # like foo() if sub foo predeclared, else bareword "foo"</pre></blockquote>Not only does the <tt class="literal">&</tt> form make the argument listoptional, but italso disables any prototype checking on the arguments you do provide.This is partly for historical reasons and partly to provide aconvenient way to cheat if you know what you're doing. See the section<a href="ch06_04.htm#ch06-sect-proto">Section 6.4, "Prototypes"</a> later in this chapter.</p><p><a name="INDEX-1831"></a>Variables you access from inside a function that haven't been declaredprivate to that function are not necessarily global variables; theystill follow the normal block-scoping rules of Perl. As explained in <a href="ch02_05.htm#ch02-sect-names">Section 6.5, "Names"</a> in <a href="ch02_01.htm">Chapter 2, "Bits and Pieces"</a>, this means theylook first in the surrounding lexical scope (or scopes) for resolution,then on to the single package scope. From the viewpoint of asubroutine, then, any <tt class="literal">my</tt> variables from an enclosing lexical scopeare still perfectly visible.</p><p>For example, the <tt class="literal">bumpx</tt> function below has access to the file-scoped<tt class="literal">$x</tt> lexical variable because the scope where the <tt class="literal">my</tt> wasdeclared--the file itself--hasn't been closed off before thesubroutine is defined:<blockquote><pre class="programlisting"># top of filemy $x = 10; # declare and initialize variablesub bumpx { $x++ } # function can see outer lexical variable</pre></blockquote><a name="INDEX-1832"></a></p><p><a name="INDEX-1833"></a>C and C++ programmers would probably think of <tt class="literal">$x</tt> as a "filestatic" variable. It's private as far as functions in other filesare concerned, but global from the perspective of functions declaredafter the <tt class="literal">my</tt>. C programmers who come to Perl lookingfor whatthey would call "static variables" for files or functions find nosuch keyword in Perl. Perl programmers generally avoid the word"static", because static systems are dead and boring, and becausethe word is so muddled in historical usage.</p><p>Although Perl doesn't include the word "static" in its lexicon,Perl programmers have no problem creating variables that are private to afunction and persist across function calls. There's just no specialword for these. Perl's richer scoping primitives combine withautomatic memory management in ways that someone looking for a"static" keyword might never think of trying.</p><p><a name="INDEX-1834"></a>Lexical variables don't get automatically garbage collected justbecause their scope has exited; they wait to get recycled until they're nolonger <em class="emphasis">used</em>, which is much more important. To create privatevariables that aren't automatically reset across function calls,enclose the whole function in an extra block and put both the <tt class="literal">my</tt>declaration and the function definition within that block. You caneven put more than one function there for shared access to anotherwise private variable:<blockquote><pre class="programlisting">{ my $counter = 0; sub next_counter { return ++$counter } sub prev_counter { return --$counter }}</pre></blockquote>As always, access to the lexical variable is limited to code withinthe same lexical scope. The names of the two functions, on the other hand,are globally accessible (within the package), and, since they weredefined inside <tt class="literal">$counter</tt>'s scope, they can still access thatvariable even though no one else can.</p><p><a name="INDEX-1835"></a><a name="INDEX-1836"></a><a name="INDEX-1837"></a><a name="INDEX-1838"></a>If this function is loaded via <tt class="literal">require</tt> or <tt class="literal">use</tt>, then this isprobably just fine. If it's all in the main program, you'll need tomake sure any run-time assignment to <tt class="literal">my</tt> is executed early enough, eitherby putting the whole block before your main program, or alternatively, byplacing a <tt class="literal">BEGIN</tt> or <tt class="literal">INIT</tt> block around it to make sure it getsexecuted before your program starts:<blockquote><pre class="programlisting">BEGIN { my @scale = ('A' .. 'G'); my $note = -1; sub next_pitch { return $scale[ ($note += 1) %= @scale ] };}</pre></blockquote>The <tt class="literal">BEGIN</tt> doesn't affect the subroutine definition, nor does it affectthe persistence of any lexicals used by the subroutine. It's justthere to ensure the variables get initialized before the subroutineis ever called. For more on declaring private and global variables,see <tt class="literal">my</tt> and <tt class="literal">our</tt> respectively in <a href="ch29_01.htm">Chapter 29, "Functions"</a>.The <tt class="literal">BEGIN</tt> and <tt class="literal">INIT</tt> constructs are explained in <a href="ch18_01.htm">Chapter 18, "Compiling"</a>.</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="ch06_01.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_03.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr><tr><td align="left" valign="top" width="172">6.1. Syntax</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.3. Passing References</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 + -