📄 perlsub.1
字号:
.PPScalars are already passed by reference, so you can modifyscalar arguments without using this mechanism by referring explicitlyto \f(CW$_[0]\fR etc. You can modify all the elements of an array by passingall the elements as scalars, but you have to use the \f(CW\*(C`*\*(C'\fR mechanism (orthe equivalent reference mechanism) to \f(CW\*(C`push\*(C'\fR, \f(CW\*(C`pop\*(C'\fR, or change the size ofan array. It will certainly be faster to pass the typeglob (or reference)..PPEven if you don't want to modify an array, this mechanism is useful forpassing multiple arrays in a single \s-1LIST\s0, because normally the \s-1LIST\s0mechanism will merge all the array values so that you can't extract outthe individual arrays. For more on typeglobs, see\&\*(L"Typeglobs and Filehandles\*(R" in perldata..Sh "When to Still Use \fIlocal()\fP".IX Xref "local variable, local".IX Subsection "When to Still Use local()"Despite the existence of \f(CW\*(C`my\*(C'\fR, there are still three places where the\&\f(CW\*(C`local\*(C'\fR operator still shines. In fact, in these three places, you\&\fImust\fR use \f(CW\*(C`local\*(C'\fR instead of \f(CW\*(C`my\*(C'\fR..IP "1." 4You need to give a global variable a temporary value, especially \f(CW$_\fR..SpThe global variables, like \f(CW@ARGV\fR or the punctuation variables, must be \&\f(CW\*(C`local\*(C'\fRized with \f(CW\*(C`local()\*(C'\fR. This block reads in \fI/etc/motd\fR, and splitsit up into chunks separated by lines of equal signs, which are placedin \f(CW@Fields\fR..Sp.Vb 6\& {\& local @ARGV = ("/etc/motd");\& local $/ = undef;\& local $_ = <>; \& @Fields = split /^\es*=+\es*$/;\& }.Ve.SpIt particular, it's important to \f(CW\*(C`local\*(C'\fRize \f(CW$_\fR in any routine that assignsto it. Look out for implicit assignments in \f(CW\*(C`while\*(C'\fR conditionals..IP "2." 4You need to create a local file or directory handle or a local function..SpA function that needs a filehandle of its own must use\&\f(CW\*(C`local()\*(C'\fR on a complete typeglob. This can be used to create new symboltable entries:.Sp.Vb 6\& sub ioqueue {\& local (*READER, *WRITER); # not my!\& pipe (READER, WRITER) or die "pipe: $!";\& return (*READER, *WRITER);\& }\& ($head, $tail) = ioqueue();.Ve.SpSee the Symbol module for a way to create anonymous symbol tableentries..SpBecause assignment of a reference to a typeglob creates an alias, thiscan be used to create what is effectively a local function, or at least,a local alias..Sp.Vb 6\& {\& local *grow = \e&shrink; # only until this block exists\& grow(); # really calls shrink()\& move(); # if move() grow()s, it shrink()s too\& }\& grow(); # get the real grow() again.Ve.SpSee \*(L"Function Templates\*(R" in perlref for more about manipulatingfunctions by name in this way..IP "3." 4You want to temporarily change just one element of an array or hash..SpYou can \f(CW\*(C`local\*(C'\fRize just one element of an aggregate. Usually thisis done on dynamics:.Sp.Vb 5\& {\& local $SIG{INT} = \*(AqIGNORE\*(Aq;\& funct(); # uninterruptible\& } \& # interruptibility automatically restored here.Ve.SpBut it also works on lexically declared aggregates. Prior to 5.005,this operation could on occasion misbehave..Sh "Pass by Reference".IX Xref "pass by reference pass-by-reference reference".IX Subsection "Pass by Reference"If you want to pass more than one array or hash into a function\*(--orreturn them from it\*(--and have them maintain their integrity, thenyou're going to have to use an explicit pass-by-reference. Before youdo that, you need to understand references as detailed in perlref.This section may not make much sense to you otherwise..PPHere are a few simple examples. First, let's pass in several arraysto a function and have it \f(CW\*(C`pop\*(C'\fR all of then, returning a new listof all their former last elements:.PP.Vb 1\& @tailings = popmany ( \e@a, \e@b, \e@c, \e@d );\&\& sub popmany {\& my $aref;\& my @retlist = ();\& foreach $aref ( @_ ) {\& push @retlist, pop @$aref;\& }\& return @retlist;\& }.Ve.PPHere's how you might write a function that returns alist of keys occurring in all the hashes passed to it:.PP.Vb 10\& @common = inter( \e%foo, \e%bar, \e%joe );\& sub inter {\& my ($k, $href, %seen); # locals\& foreach $href (@_) {\& while ( $k = each %$href ) {\& $seen{$k}++;\& }\& }\& return grep { $seen{$_} == @_ } keys %seen;\& }.Ve.PPSo far, we're using just the normal list return mechanism.What happens if you want to pass or return a hash? Well,if you're using only one of them, or you don't mind themconcatenating, then the normal calling convention is ok, althougha little expensive..PPWhere people get into trouble is here:.PP.Vb 3\& (@a, @b) = func(@c, @d);\&or\& (%a, %b) = func(%c, %d);.Ve.PPThat syntax simply won't work. It sets just \f(CW@a\fR or \f(CW%a\fR andclears the \f(CW@b\fR or \f(CW%b\fR. Plus the function didn't get passedinto two separate arrays or hashes: it got one long list in \f(CW@_\fR,as always..PPIf you can arrange for everyone to deal with this through references, it'scleaner code, although not so nice to look at. Here's a function thattakes two array references as arguments, returning the two array elementsin order of how many elements they have in them:.PP.Vb 10\& ($aref, $bref) = func(\e@c, \e@d);\& print "@$aref has more than @$bref\en";\& sub func {\& my ($cref, $dref) = @_;\& if (@$cref > @$dref) {\& return ($cref, $dref);\& } else {\& return ($dref, $cref);\& }\& }.Ve.PPIt turns out that you can actually do this also:.PP.Vb 10\& (*a, *b) = func(\e@c, \e@d);\& print "@a has more than @b\en";\& sub func {\& local (*c, *d) = @_;\& if (@c > @d) {\& return (\e@c, \e@d);\& } else {\& return (\e@d, \e@c);\& }\& }.Ve.PPHere we're using the typeglobs to do symbol table aliasing. It'sa tad subtle, though, and also won't work if you're using \f(CW\*(C`my\*(C'\fRvariables, because only globals (even in disguise as \f(CW\*(C`local\*(C'\fRs)are in the symbol table..PPIf you're passing around filehandles, you could usually just use the baretypeglob, like \f(CW*STDOUT\fR, but typeglobs references work, too.For example:.PP.Vb 5\& splutter(\e*STDOUT);\& sub splutter {\& my $fh = shift;\& print $fh "her um well a hmmm\en";\& }\&\& $rec = get_rec(\e*STDIN);\& sub get_rec {\& my $fh = shift;\& return scalar <$fh>;\& }.Ve.PPIf you're planning on generating new filehandles, you could do this.Notice to pass back just the bare *FH, not its reference..PP.Vb 5\& sub openit {\& my $path = shift;\& local *FH;\& return open (FH, $path) ? *FH : undef;\& }.Ve.Sh "Prototypes".IX Xref "prototype subroutine, prototype".IX Subsection "Prototypes"Perl supports a very limited kind of compile-time argument checkingusing function prototyping. If you declare.PP.Vb 1\& sub mypush (\e@@).Ve.PPthen \f(CW\*(C`mypush()\*(C'\fR takes arguments exactly like \f(CW\*(C`push()\*(C'\fR does. Thefunction declaration must be visible at compile time. The prototypeaffects only interpretation of new-style calls to the function,where new-style is defined as not using the \f(CW\*(C`&\*(C'\fR character. Inother words, if you call it like a built-in function, then it behaveslike a built-in function. If you call it like an old-fashionedsubroutine, then it behaves like an old-fashioned subroutine. Itnaturally falls out from this rule that prototypes have no influenceon subroutine references like \f(CW\*(C`\e&foo\*(C'\fR or on indirect subroutinecalls like \f(CW\*(C`&{$subref}\*(C'\fR or \f(CW\*(C`$subref\->()\*(C'\fR..PPMethod calls are not influenced by prototypes either, because thefunction to be called is indeterminate at compile time, sincethe exact code called depends on inheritance..PPBecause the intent of this feature is primarily to let you definesubroutines that work like built-in functions, here are prototypesfor some other functions that parse almost exactly like thecorresponding built-in..PP.Vb 1\& Declared as Called as\&\& sub mylink ($$) mylink $old, $new\& sub myvec ($$$) myvec $var, $offset, 1\& sub myindex ($$;$) myindex &getstring, "substr"\& sub mysyswrite ($$$;$) mysyswrite $buf, 0, length($buf) \- $off, $off\& sub myreverse (@) myreverse $a, $b, $c\& sub myjoin ($@) myjoin ":", $a, $b, $c\& sub mypop (\e@) mypop @array\& sub mysplice (\e@$$@) mysplice @array, @array, 0, @pushme\& sub mykeys (\e%) mykeys %{$hashref}\& sub myopen (*;$) myopen HANDLE, $name\& sub mypipe (**) mypipe READHANDLE, WRITEHANDLE\& sub mygrep (&@) mygrep { /foo/ } $a, $b, $c\& sub myrand (;$) myrand 42\& sub mytime () mytime.Ve.PPAny backslashed prototype character represents an actual argumentthat absolutely must start with that character. The value passedas part of \f(CW@_\fR will be a reference to the actual argument givenin the subroutine call, obtained by applying \f(CW\*(C`\e\*(C'\fR to that argument..PPYou can also backslash several argument types simultaneously by usingthe \f(CW\*(C`\e[]\*(C'\fR notation:.PP.Vb 1\& sub myref (\e[$@%&*]).Ve.PPwill allow calling \fImyref()\fR as.PP.Vb 5\& myref $var\& myref @array\& myref %hash\& myref &sub\& myref *glob.Ve.PPand the first argument of \fImyref()\fR will be a reference toa scalar, an array, a hash, a code, or a glob..PPUnbackslashed prototype characters have special meanings. Anyunbackslashed \f(CW\*(C`@\*(C'\fR or \f(CW\*(C`%\*(C'\fR eats all remaining arguments, and forceslist context. An argument represented by \f(CW\*(C`$\*(C'\fR forces scalar context. An\&\f(CW\*(C`&\*(C'\fR requires an anonymous subroutine, which, if passed as the firstargument, does not require the \f(CW\*(C`sub\*(C'\fR keyword or a subsequent comma..PPA \f(CW\*(C`*\*(C'\fR allows the subroutine to accept a bareword, constant, scalar expression,typeglob, or a reference to a typeglob in that slot. The value will beavailable to the subroutine either as a simple scalar, or (in the lattertwo cases) as a reference to the typeglob. If you wish to always convertsuch arguments to a typeglob reference, use \fISymbol::qualify_to_ref()\fR asfollows:.PP.Vb 1\& use Symbol \*(Aqqualify_to_ref\*(Aq;\&\& sub foo (*) {\& my $fh = qualify_to_ref(shift, caller);\& ...\& }.Ve.PPA semicolon (\f(CW\*(C`;\*(C'\fR) separates mandatory arguments from optional arguments.It is redundant before \f(CW\*(C`@\*(C'\fR or \f(CW\*(C`%\*(C'\fR, which gobble up everything else..PPAs the last character of a prototype, or just before a semicolon, you canuse \f(CW\*(C`_\*(C'\fR in place of \f(CW\*(C`$\*(C'\fR: if this argument is not provided, \f(CW$_\fR will beused instead..PPNote how the last three examples in the table above are treatedspecially by the parser. \f(CW\*(C`mygrep()\*(C'\fR is parsed as a true listoperator, \f(CW\*(C`myrand()\*(C'\fR is parsed as a true unary operator with unaryprecedence the same as \f(CW\*(C`rand()\*(C'\fR, and \f(CW\*(C`mytime()\*(C'\fR is truly withoutarguments, just like \f(CW\*(C`time()\*(C'\fR. That is, if you say.PP.Vb 1\& mytime +2;.Ve.PPyou'll get \f(CW\*(C`mytime() + 2\*(C'\fR, not \f(CWmytime(2)\fR, which is how it would be parsedwithout a prototype..PPThe interesting thing about \f(CW\*(C`&\*(C'\fR is that you can generate new syntax with it,provided it's in the initial position:.IX Xref "&".PP.Vb 9\& sub try (&@) {\& my($try,$catch) = @_;\& eval { &$try };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -