第六章 子过程:
1.0 语法:
声明一个命名子过程,但不定义它,使用下面的形式;
sub NAME
sub NAME PROTO
声明并且定义一个命名子过程,加上一个BLOCK
sub NAME BLOCK
创建一个匿名子过程或子句,把NAME去掉就可以
对于没有NAME 的形式,你还必须提供调用子过程的方法,因此你必须保存返回值,因为 这种形式的sub声明方法
不但在编译的时候编译,同时也产生一个运行时的返回值,所以我们就可以保证保存它。
$subref = sub BLOCK;
可以用下面的方法引入在另一个模块中定义的子过程:
use MODULE qw(NAME1 NAME2 ...); ##在调用模块时经常见到
直接调用子过程可以用下面的方法:
NAME(LIST) ##有圆括弧时 &是可选的
NAME LIST ##如果预声明/输入子过程,那么圆括弧是可选的
&NAME ##把当前的@_输出到该子过程
间接调用子过程(通过名字或引用), 可以使用下面的任何一种方法:
1.&$subref(LIST) ##在间接调用的时候,&不能忽略
2.$subref->(LIST) ##(除非使用中缀表示法)
3. &$subref ##把当前的@_输出到该子过程
或者当你使用$subref = &name来获取一个命名子过程的引用的时候,同样,当你使用&$subref()或&{$subref()}
进行一个间接子过程引用的时候。
或者当你使用$subref = &name来获取一个命名子过程的引用的时候,同样,当你使用
&$subref()或&{$subref()}进行一个间接子过程调用的时候也不能省略&
2.0 语意:
在你记住所有语法前,你只需要记住下边这种定义子过程的普通方法:
sub razzle {
print "OK,you've been razzled.
";
}
和调用子过程的正常方法就是:
razzle();
现在,如果你将设计一种可以支持不定数量的任意参数的语言,你最好让你的语言在处理这些任意长的参数列表上容易些。
所有传入Perl过程的参数都是以@_身份传入的。如果你调用一个有两个参数的函数,它们在函数内部可以作为@_数组的前两个成
员访问:
$_[0] 和$_[1] .
因为@_ 只是一个有着奇怪名字的数组,所以你可以像处理普通数组一样随意处理它。
子过程(其他的程序块也一样)的返回值是过程最后一个表达式的值,或者你可以在子过程的任何一个地方明确使用一个return
语句来返回值并且退出子过程,不管是那种方法,
zjzc01:/root/big2# cat a1.pl
sub aysetnv {
my ($key,$value) = @_;
$hash{$key} = $value };
aysetnv(a,8888);
print $hash{a}."
";
zjzc01:/root/big2# perl a1.pl
8888
但是没人要你一定要给你的参数命名,这就是@_数组的全部观点。例如,计算一个最大值,你可以简单直接遍历@_数组:
函数返回值最大值:
zjzc01:/root/big2# cat a2.pl
sub max {
$max = shift (@_);
for my $item (@_){
$max = $item if $max < $item;
}
return $max;
};
$value = max(1,5,2,44,33,23,7);
print "$value is $value
";
zjzc01:/root/big2# perl a2.pl
$value is 44
zjzc01:/root/big2# cat a1.pl
sub aysetnv {
my ($key,$value) = @_;
$hash{$key} = $value;
resturn -1 };
$result=aysetnv(a,xxx);
print "$result is $result
";
zjzc01:/root/big2# perl a1.pl
$result is -1
函数返回值:
或者你可以一次将@_ 填入一个散列:
zjzc01:/root/big2# cat a3.pl
sub configuration {
my %options = @_;
print "Maximum verbosity.
" if $options{VERBOSE} == 9;
}
configuration(PASSWORD => 'xyzzy', VERBOSE => 9, SOCRE => 0);
print %options;
zjzc01:/root/big2# perl a3.pl
Maximum verbosity.
zjzc01:/root/big2#
2.2 错误提示:
如果你希望你的函数能够以特定的方式返回,使调用者能够得知发生了一个错误.在Perl中实现这个目的的最自然的一种方法就是
用一个不菲参数的return 语句。这样当函数在标量环境中使用时,调用者得到一个undef,如果在列表环境中使用,调用者得到一
个空列表。
3.0 传入引用:
这里有几个简单的例子,首先,让我们定义一个函数,这个函数使用数组的引用作为参数。
当这个数组非常大时,作为一个引用传递要比传入一场列值要快的多:
zjzc01:/root/big2# cat a4.pl
@a=qw/1 3 9 10/;
$total = sum (@a);
sub sum {
my ($aref) = @_;
foreach (@$aref) {$total += $_}
return $total;
};
print "$total is $total
";
zjzc01:/root/big2# perl a4.pl
$total is 23
下面让我们将几个数组传入一个函数,并且使用pop得到每个数组的最后一个元素,并返回每个数组最后一个元素组成的一个新的
数组:
zjzc01:/root/big2# cat a5.pl
@a=qw/1 2 3/;
@b=qw/4 5 6/;
@c=qw/7 8 9/;
@d=qw/a b c/;
@tailings = popmany(@a,@b,@c,@d);
sub popmany {
my @retlist = ();
for my $aref (@_) {
push @retlist, pop @$aref;
}
return @retlist;
}
;
print "@tailings is @tailings
";
zjzc01:/root/big2# perl a5.pl
@tailings is 3 6 9 c
zjzc01:/root/big2#
4.0 函数原型:
Perl 可以让你定义你自己的函数,这些函数可以像Perl的内建函数一样调用.例如
push (@array,$item),它必须接收一个@array的引用,而不仅仅是@array中的值