📄 ch06_02.htm
字号:
<html><head><title>Semantics (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Semantics"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><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="ch06_01.htm">Chapter 6: Subroutines</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></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">6.2. Semantics</h2><p><a name="INDEX-1803"></a><a name="INDEX-1804"></a>Before you get too worked up over all that syntax, just rememberthat the normal way to define a simple subroutine ends up lookinglike this:<blockquote><pre class="programlisting">sub razzle { print "Ok, you've been razzled.\n";}</pre></blockquote>and the normal way to call it is simply:<blockquote><pre class="programlisting">razzle();</pre></blockquote><a name="INDEX-1805"></a><a name="INDEX-1806"></a><a name="INDEX-1807"></a>In this case, we ignored inputs (arguments) and outputs(return values). But the Perl model for passing data into and out ofa subroutine is really quite simple: all function parameters are passed as onesingle, flat list of scalars, and multiple return values are likewisereturned to the caller as one single, flat list of scalars. Aswith any <em class="replaceable">LIST</em>, any arrays or hashes passed in these lists willinterpolate their values into the flattened list, losing theiridentities--but there are several ways to get around this, and theautomatic list interpolation is frequently quite useful. Bothparameter lists and return lists may contain as many or as fewscalar elements as you'd like (though you may put constraints onthe parameter list by using prototypes). Indeed, Perl is designedaround this notion of <em class="emphasis">variadic</em> functions (those taking any numberof arguments), unlike C, where they're sort of grudgingly kludgedin so that you can call <em class="emphasis">printf</em>(3).<a name="INDEX-1808"></a></p><p><a name="INDEX-1809"></a><a name="INDEX-1810"></a><a name="INDEX-1811"></a>Now, if you're going to design a language around the notion of passingvarying numbers of arbitrary arguments, you'd better make it easy toprocess those arbitrary lists of arguments. Any arguments passed to aPerl routine come in as the array <tt class="literal">@_</tt>. If you call a function withtwo arguments, they are accessible inside the function as the first twoelements of that array: <tt class="literal">$_[0]</tt> and <tt class="literal">$_[1]</tt>. Since <tt class="literal">@_</tt> is a just aregular array with an irregular name, you can do anything to it you'dnormally do to an array.<a href="#FOOTNOTE-2">[2]</a>The array <tt class="literal">@_</tt> is a local array, but its values are aliases to theactual scalar parameters. (This is known as pass-by-referencesemantics.) Thus you can modify the actual parameters if you modifythe corresponding element of <tt class="literal">@_</tt>. (This is rarely done, however,since it's so easy to return interesting values in Perl.)<a name="INDEX-1812"></a><a name="INDEX-1813"></a></p><blockquote class="footnote"><a name="FOOTNOTE-2"></a><p>[2] This is an area where Perl is<em class="emphasis">more</em> orthogonal than the typical programming language.</p></blockquote><p><a name="INDEX-1814"></a><a name="INDEX-1815"></a><a name="INDEX-1816"></a><a name="INDEX-1817"></a>The return value of the subroutine (or of any other block, for thatmatter) is the value of the last expression evaluated. Or you may usean explicit <tt class="literal">return</tt> statement to specify the return value and exit thesubroutine from any point in the subroutine. Either way, as thesubroutine is called in a scalar or list context, so also is the finalexpression of the routine evaluated in that same scalar or list context.</p><h3 class="sect2">6.2.1. Tricks with Parameter Lists</h3><p><a name="INDEX-1818"></a><a name="INDEX-1819"></a><a name="INDEX-1820"></a><a name="INDEX-1821"></a>Perl does not yet have named formal parameters, but in practice all youdo is copy the values of <tt class="literal">@_</tt> to a <tt class="literal">my</tt> list, which serves nicely fora list of formal parameters. (Not coincidentally, copying the valueschanges the pass-by-reference semantics into pass-by-value, which ishow people usually expect parameters to work anyway, even if theydon't know the fancy computer science terms for it.) Here's a typicalexample:<blockquote><pre class="programlisting">sub maysetenv { my ($key, $value) = @_; $ENV{$key} = $value unless $ENV{$key};}</pre></blockquote><a name="INDEX-1822"></a>But you aren't required to name your parameters, which is the wholepoint of the <tt class="literal">@_</tt> array. For example, to calculate a maximum, you canjust iterate over <tt class="literal">@_</tt> directly:<blockquote><pre class="programlisting">sub max { my $max = shift(@_); for my $item (@_) { $max = $item if $max < $item; } return $max;}$bestday = max($mon,$tue,$wed,$thu,$fri);</pre></blockquote>Or you can fill an entire hash at once:<blockquote><pre class="programlisting">sub configuration { my %options = @_; print "Maximum verbosity.\n" if $options{VERBOSE} == 9;}configuration(PASSWORD => "xyzzy", VERBOSE => 9, SCORE => 0);</pre></blockquote><a name="INDEX-1823"></a>Here's an example of not naming your formal arguments so that youcan modify your actual arguments:<blockquote><pre class="programlisting">upcase_in($v1, $v2); # this changes $v1 and $v2sub upcase_in { for (@_) { tr/a-z/A-Z/ }}</pre></blockquote><a name="INDEX-1824"></a>You aren't allowed to modify constants in this way, of course. If anargument were actually a scalar literal like <tt class="literal">"hobbit"</tt> or read-onlyscalar variable like <tt class="literal">$1</tt>, and you tried to change it, Perl wouldraise an exception (presumably fatal, possibly career-threatening).For example, this won't work:<blockquote><pre class="programlisting">upcase_in("frederick");</pre></blockquote>It would be much safer if the <tt class="literal">upcase_in</tt> function were written toreturn a copy of its parameters instead of changing them in place:<blockquote><pre class="programlisting">($v3, $v4) = upcase($v1, $v2);sub upcase { my @parms = @_; for (@parms) { tr/a-z/A-Z/ } # Check whether we were called in list context. return wantarray ? @parms : $parms[0];}</pre></blockquote>Notice how this (unprototyped) function doesn't care whether it waspassed real scalars or arrays. Perl will smash everything into one big,long, flat <tt class="literal">@_</tt> parameter list. This is one of the places where Perl'ssimple argument-passing style shines. The <tt class="literal">upcase</tt> function will workperfectly well without changing the <tt class="literal">upcase</tt> definition even if we feed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -