📄 ch04_05.htm
字号:
<html><head><title>Arguments (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_04.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_06.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr></table></div><h2 class="sect1">4.5. Arguments</h2><p><a name="INDEX-330" />Thatsubroutine called <tt class="literal">larger_of_fred_or_barney</tt> wouldbe much more useful if it didn't force us to use the globalvariables <tt class="literal">$fred</tt> and <tt class="literal">$barney</tt>.That's because, if we wanted to get the larger value from<tt class="literal">$wilma</tt> and <tt class="literal">$betty</tt>, we currentlyhave to copy those into <tt class="literal">$fred</tt> and<tt class="literal">$barney</tt> before we can use<tt class="literal">larger_of_fred_or_barney</tt>. And if we had somethinguseful in those variables, we'd have to first copy those toother variables, say <tt class="literal">$save_fred</tt> and<tt class="literal">$save_barney</tt>. And then, when we're done withthe subroutine, we'd have to copy those back to<tt class="literal">$fred</tt> and <tt class="literal">$barney</tt> again.</p><p>Luckily, Perl has subroutine arguments. To pass an argument list tothe subroutine, simply place the list expression, in parentheses,after the subroutine invocation, like this:</p><blockquote><pre class="code">$n = &max(10, 15); # This sub call has two parameters</pre></blockquote><p><a name="INDEX-331" />That list is<em class="firstterm">passed</em> to the subroutine; that is, it'smade available for the subroutine to use however it needs to. Ofcourse, this list has to be stored into a variable, so the<a name="INDEX-332" /><a name="INDEX-333" />parameter list (another name for the argumentlist) is automatically assigned to a special array variable named<tt class="literal">@_</tt> for the duration of the subroutine. Thesubroutine can access this variable to determine both the number ofarguments and the value of those arguments.</p><p>So, that means that the first subroutine parameter is stored in<tt class="literal">$_[0]</tt>, the second one is stored in<tt class="literal">$_[1]</tt>, and so on. But -- and here's animportant note -- these variables have nothing whatsoever to dowith the <tt class="literal">$_</tt> variable, any more than<tt class="literal">$dino[3]</tt> (an element of the<tt class="literal">@dino</tt> array) has to do with<tt class="literal">$dino</tt> (a completely distinct scalar variable).It's just that the parameter list must be stored into somearray variable for the subroutine to use it, and Perl uses the array<tt class="literal">@_</tt> for this purpose.</p><p>Now, you <em class="emphasis">could</em> write the subroutine<tt class="literal">&max</tt> to look a little like the subroutine<tt class="literal">&larger_of_fred_or_barney</tt>, but instead ofusing <tt class="literal">$a</tt> you <em class="emphasis">could</em> use thefirst subroutine parameter (<tt class="literal">$_[0]</tt>), and instead ofusing <tt class="literal">$b</tt>, you <em class="emphasis">could</em> use thesecond subroutine parameter (<tt class="literal">$_[1]</tt>). And so you<em class="emphasis">could</em> end up with code something like this:</p><blockquote><pre class="code">sub max { # Compare this to &larger_of_fred_or_barney if ($_[0] > $_[1]) { $_[0]; } else { $_[1]; }}</pre></blockquote><p>Well, as we said, you <em class="emphasis">could</em> do that. Butit's pretty ugly with all of those subscripts, and hard toread, write, check, and debug, too. We'll see a better way in amoment.</p><p>There's another problem with this subroutine. The name<tt class="literal">&max</tt><a name="INDEX-334" /> is nice and short, but itdoesn't remind us that this subroutine works properly only ifcalled with exactly two parameters:</p><blockquote><pre class="code">$n = &max(10, 15, 27); # Oops!</pre></blockquote><p>Excess parameters are ignored -- since the subroutine never looksat <tt class="literal">$_[2]</tt>, Perl doesn't care whetherthere's something in there or not. And insufficient parametersare also ignored -- you simply get <tt class="literal">undef</tt> if youlook beyond the end of the <tt class="literal">@_</tt> array, as with anyother array. We'll see how to make a better<tt class="literal">&max</tt>, which works with any number ofparameters, later in this chapter.</p><p>The <tt class="literal">@_</tt> variable is local to thesubroutine;<a href="#FOOTNOTE-106">[106]</a> ifthere's a global value in <tt class="literal">@_</tt>, it is savedaway before the subroutine is invoked and restored to its previousvalue upon return from the subroutine.<a href="#FOOTNOTE-107">[107]</a> This also means that a subroutine can pass arguments toanother subroutine without fear of losing its own<tt class="literal">@_</tt> variable -- the nested subroutine invocationgets its own <tt class="literal">@_</tt> in the same way. Even if thesubroutine calls itself recursively, each invocation gets a new<tt class="literal">@_</tt>, so <tt class="literal">@_</tt> is always theparameter list for the currentsubroutine<a name="INDEX-335" /> invocation.<a name="INDEX-336" /></p><blockquote class="footnote"> <a name="FOOTNOTE-106" /><p>[106]Unless there's an ampersand infront of the name for the invocation, and no parentheses (orarguments) afterward, in which case the <tt class="literal">@_</tt> arrayis inherited from the caller's context. That's generallya bad idea, but is occasionally useful.</p> </blockquote><blockquote class="footnote"> <a name="FOOTNOTE-107" /><p>[107]You mightrecognize that this is the same mechanism as used with the controlvariable of the <tt class="literal">foreach</tt> loop, as seen in theprevious chapter. In either case, the variable's value is savedand automatically restored by Perl. We'll see this again withthe <tt class="literal">local</tt> operator later in this chapter.</p></blockquote><hr width="684" align="left" /><div class="navbar"><table width="684" border="0"><tr><td align="left" valign="top" width="228"><a href="ch04_04.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_06.htm"><img alt="Next" border="0" src="../gifs/txtnexta.gif" /></a></td></tr><tr><td align="left" valign="top" width="228">4.4. Return Values</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.6. Private Variables in Subroutines</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 + -