📄 ch04_08.htm
字号:
<html><head><title>Variable-length Parameter Lists (Learning Perl, 3rd Edition)</title><link rel="stylesheet" type="text/css" href="../style/style1.css" /><meta name="DC.Creator" content="Randal L. Schwartz and Tom Phoenix" /><meta name="DC.Format" content="text/xml" scheme="MIME" /><meta name="DC.Language" content="en-US" /><meta name="DC.Publisher" content="O'Reilly & Associates, Inc." /><meta name="DC.Source" scheme="ISBN" content="0596001320L" /><meta name="DC.Subject.Keyword" content="stuff" /><meta name="DC.Title" content="Learning Perl, 3rd Edition" /><meta name="DC.Type" content="Text.Monograph" /></head><body bgcolor="#ffffff"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Learning Perl, 3rd Edition" /><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch04_07.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"></a></td><td align="right" valign="top" width="228"><a href="ch04_09.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">4.8. Variable-length Parameter Lists</h2><p><a name="INDEX-348" /><a name="INDEX-349" />In real-world Perl code, subroutines areoften given parameter lists of arbitrary length. That's becauseof Perl's "no unnecessary limits" philosophy thatwe've already seen. Of course, this is unlike many traditionalprogramming languages, which require every subroutine to be strictlytyped; that is, to permit only a certain, predefined number ofparameters of predefined types. It's nice that Perl is soflexible, but (as we saw with the <tt class="literal">&max</tt> routineearlier) that may cause problems when a subroutine is called with adifferent number of arguments than the author expected.</p><p>Of course, the subroutine can easily check that it has the rightnumber of arguments by examining the <tt class="literal">@_</tt> array. Forexample, we could have written <tt class="literal">&max</tt> to checkits argument list like this:<a href="#FOOTNOTE-113">[113]</a></p><blockquote class="footnote"> <a name="FOOTNOTE-113" /><p>[113]As soon as you learnabout <tt class="literal">warn</tt> (in <a href="ch11_01.htm">Chapter 11, "Filehandles and File Tests"</a>),you'll see that you can use it to turn improper usage like thisinto a proper warning. Or perhaps you'll decide that this caseis severe enough to warrant using <tt class="literal">die</tt>, describedin the same chapter.</p> </blockquote><blockquote><pre class="code">sub max { if (@_ != 2) { print "WARNING! &max should get exactly two arguments!\n"; } # continue as before... . . .}</pre></blockquote><p>That <tt class="literal">if</tt>-test uses the "name" of thearray in a scalar context to find out the number of array elements,as we saw in <a href="ch03_01.htm">Chapter 3, "Lists and Arrays "</a>.</p><p>But in real-world Perl programming, this sort of check is hardly everused; it's better to make the subroutine adapt to theparameters.</p><a name="lperl3-CHP-4-SECT-8.1" /><div class="sect2"><h3 class="sect2">4.8.1. A Better &max Routine</h3><p>So let's rewrite<tt class="literal">&max</tt><a name="INDEX-350" /> to allow for any number ofarguments:</p><blockquote><pre class="code">$maximum = &max(3, 5, 10, 4, 6);sub max { my($max_so_far) = shift @_; # the first one is the largest yet seen foreach (@_) { # look at the remaining arguments if ($_ > $max_so_far) { # could this one be bigger yet? $max_so_far = $_; } } $max_so_far;}</pre></blockquote><p>This code uses what has often been called the "high-watermark" algorithm; after a flood, when the waters have surged andreceded for the last time, the high-water mark shows where thehighest water was seen. In this routine,<tt class="literal">$max_so_far</tt> keeps track of our high-water mark,the largest number yet seen.</p><p>The first line sets <tt class="literal">$max_so_far</tt> to<tt class="literal">3</tt> (the first parameter in the example code) byshifting that parameter from the parameter array,<tt class="literal">@_</tt>. So <tt class="literal">@_</tt> now holds<tt class="literal">(5, 10,</tt> <tt class="literal">4, 6)</tt>, since the<tt class="literal">3</tt> has been shifted off. And the largest number yetseen is the <em class="emphasis">only</em> one yet seen:<tt class="literal">3</tt>, the first parameter.</p><p>Now, the <tt class="literal">foreach</tt> loop will step through theremaining values in the parameter list, from <tt class="literal">@_</tt>.The control variable of the loop is, by default,<tt class="literal">$_</tt>. (But, remember, there's no automaticconnection between <tt class="literal">@_</tt> and <tt class="literal">$_</tt>;it's just a coincidence that they have such similar names.) Thefirst time through the loop, <tt class="literal">$_</tt> is<tt class="literal">5</tt>. The <tt class="literal">if</tt> test sees that it islarger than <tt class="literal">$max_so_far</tt>, so<tt class="literal">$max_so_far</tt> is set to<tt class="literal">5</tt> -- the new high-water mark.</p><p>The next time through the loop, <tt class="literal">$_</tt> is<tt class="literal">10</tt>. That's a new record high, so it'sstored in <tt class="literal">$max_so_far</tt> as well.</p><p>The next time, <tt class="literal">$_</tt> is <tt class="literal">4</tt>. The<tt class="literal">if</tt> test fails, since that's no larger than<tt class="literal">$max_so_far</tt>, which is <tt class="literal">10</tt>, sothe body of the <tt class="literal">if</tt> is skipped.</p><p>The next time, <tt class="literal">$_</tt> is <tt class="literal">6</tt>, and thebody of the <tt class="literal">if</tt> is skipped again. And that was thelast time through the loop, so the loop is done.</p><p>Now, <tt class="literal">$max_so_far</tt> becomes the return value.It's the largest number we've seen, and we've seenthem all, so it must be the largest from the list:<tt class="literal">10</tt>. </p></div><a name="lperl3-CHP-4-SECT-8.2" /><div class="sect2"><h3 class="sect2">4.8.2. Empty Parameter Lists</h3><p>That improved <tt class="literal">&max</tt> algorithm works fine now,even if there are more than two <a name="INDEX-351" />parameters.But what happens if there are none?</p><p>At first, it may seem too esoteric to worry about. After all, whywould someone call <tt class="literal">&max</tt> without giving it anyparameters? But maybe someone wrote a line like this one:</p><blockquote><pre class="code">$maximum = &max(@numbers);</pre></blockquote><p>And the array <tt class="literal">@numbers</tt> might sometimes be an emptylist; perhaps it was read in from a file that turned out to be empty,for example. So what does <tt class="literal">&max</tt> do in thatcase?</p><p>The first line of the subroutine sets <tt class="literal">$max_so_far</tt>by using <tt class="literal">shift</tt> on <tt class="literal">@_</tt>, the (nowempty) parameter array. That's harmless; the array is leftempty, and <tt class="literal">shift</tt> returns <tt class="literal">undef</tt>to <tt class="literal">$max_so_far</tt>.</p><p>Now the <tt class="literal">foreach</tt> loop wants to iterate over<tt class="literal">@_</tt>, but since that's empty, the loop body isexecuted zero times.</p><p>So in short order, Perl returns the value of<tt class="literal">$max_so_far</tt> -- <tt class="literal">undef</tt> -- asthe return value of the subroutine. In some sense, that's theright answer, because there is no largest value in an empty list.</p><p>Of course, whoever is calling this subroutine should be aware thatthe return value may be <tt class="literal">undef</tt> -- or they couldsimply ensure that the parameter list is never empty.<a name="INDEX-352" /> <a name="INDEX-353" /></p></div><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch04_07.htm"><img alt="Previous" border="0" src="../gifs/txtpreva.gif" /></a></td><td align="center" valign="top" width="228"><a href="index.htm"><img alt="Home" border="0" src="../gifs/txthome.gif" /></a></td><td align="right" valign="top" width="228"><a href="ch04_09.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">4.7. The local Operator</td><td align="center" valign="top" width="228"><a href="index/index.htm"><img alt="Book Index" border="0" src="../gifs/index.gif" /></a></td><td align="right" valign="top" width="228">4.9. Notes on Lexical (my) Variables</td></tr></table></div><hr width="684" align="left" /><img alt="Library Navigation Links" border="0" src="../gifs/navbar.gif" usemap="#library-map" /><p><p><font size="-1"><a href="copyrght.htm">Copyright © 2002</a> O'Reilly & Associates. All rights reserved.</font></p><map name="library-map"><area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -