一、子程序含义及命名规则
- perl中的子程序即是用户自己定义的函数
- 子程序的名称也是perl的标识符,即由字母、数字、下划线组成,但不能由数字开头
二、定义子程序
- 子程序由关键字sub、子程序名及花括号内的代码块组成
- 子程序的定义是全局的
- 不需对子程序事先声明
- 可在任意位置定义
- 若存在重名子程序,后面的子程序将覆盖前面的
三、调用子程序
- 可在任意表达式中使用“&子程序名”来调用子程序
- 若子程序的调用是在子程序声明的后面,且子程序名不跟内置函数重名,则可在调用子程序时省略&号
例:
&printNum; # 打印:number 1
printNum; # 打印:number 2,此处省略了&号
&printNum; # 打印:number 3
四、子程序返回值
- 每个子程序都有一个返回值
- 返回值是子程序中最后执行的表达式
例1:返回值为标量
sub printNum {
print "The return value is";
$x + $y; # $x + $y是子程序的返回值
}
$x = 2;
$y = 3;
$return = &printNum;
print " $return";
运行结果:
The return value is 5
例2:
sub printNum {
$x = 3; # $x + $y不是子程序的返回值
print "The return value is not $x!/n"; # 最后执行的表达式不是$x,而是print语句,打印成功返回真值(一般是1),若失败返回假值0
}
$return = &printNum;
print "The return value is $return.";
运行结果:
The return value is not 3!
The return value is 1.
例3:返回值为非标量
sub reList {
if ($a < $b) {
$a..$b; # 从$a到$b的列表
} else {
reverse $a..$b; # 从$b到$a的列表,因为范围操作符“..”只能递增不能递减,所以此处用reverse倒序
}
}
$a = 10;
$b = 5;
@result = &reList; # @result的值为(10, 9, 8, 7, 6, 5)
四、子程序参数
- 参数传递:只需在子程序调用后面加上括号括起来的列表表达时即可
- perl会自动将参数列表存入特殊的数组变量@_,该变量在子程序执行期间有效
- @_的第1个参数为$_[0],第二个参数为$_[1],依此类推
例:输出子程序的最大参数
sub max {
if ($_[0] > $_[1]) {
$_[0];
} else {
$_[1];
}
}
$max0 = &max(); # 空参数的子程序调用,&max()相当于&max
$max1 = &max(5); # 包含一个参数的子程序调用,$_[1]超出数组边界,得到undef
$max2 = &max(5, 10); # 包含两个参数的子程序调用
$max3 = &max(5, 10, 15); # 包含三个参数的子程序调用,最后一个参数未使用,被忽略
print "The biggest parameter is $max0./n";
print "The biggest parameter is $max1./n";
print "The biggest parameter is $max2./n";
print "The biggest parameter is $max3./n";
运行结果:
The biggest parameter is .
The biggest parameter is 5.
The biggest parameter is 10.
The biggest parameter is 10.
例:限制子程序参数个数
sub max {
if (@_ != 2) { # 这里直接用数组名称来取得数组元素个数,即子程序的参数个数
print "WARNING:$max should get exactly two arguments!/n";
}
# 其余代码略
}
五、私有变量
- 运用my操作符来创建私有变量
例:
my($a); # 声明单个私有变量
my $a; # 声明单个私有变量
- 私有变量作用范围在语句块内,包括子程序、foreach、if等所有语句块
my($a, $b); # 声明多个私有变量
my $a, $b; # 声明了一个似有变量$a和一个全局变量$b
my @a; # 声明一个私有数组变量
- 私有变量赋值
例:
my($a) = 3; # 相当于my($a); $a = 3;两句
my($a, $b) = (3, 4); # 相当于my ($a, $b); ($a, $b) = (3, 4);
my $a, $b = (3, 4); # 声明一个私有变量$a和一个全局变量$b,并赋值
my @a = qw/a b c /; # 声明一个私有数组变量,并赋值
my($a, $b, $c) = @a ; # 将@a中的元素分别赋值给三个私有变量
my($a) = @a ; # 列表上下文:将@a中的第一个元素赋值给$a,$a值为a
my $a = @a ; # 标量上下文:将@a中的元素个数赋给$a,$a值为3
- 私有变量作用范围在语句块内,包括子程序、foreach、if等所有语句块
例1:求数组最大值
$maximum = &getMax(3,5,10,4,6);
print "The maximum is $maximum.";
sub getMax {
my($max) = shift @_; #删除数组中第一个值并放入$max中
foreach (@_) { #遍历@_中其他元素,foreach中省略了控制变量,默认$_为控制变量
if ($_ > $max) { #循环中的当前元素$_大于$max?
$max = $_;
}
}
$max; #返回数组中的最大值
}
运行结果:
The maximum is 10.
例2:
foreach (1..10) {
my($square) = $_ * $_;
print "$_ squared is $square./n";
}
运行结果:
1 squared is 1.
2 squared is 4.
3 squared is 9.
4 squared is 16.
5 squared is 25.
6 squared is 36.
7 squared is 49.
8 squared is 64.
9 squared is 81.
10 squared is 100.
- 持久化私有变量state(在Perl5.10中才有),可在子程序的多次调用间保留变量的值,并将变量的作用域局限于子程序中
例:
use 5.010;
&running_sum(5, 6);
&running_sum(1..3);
&running_sum(4);
sub running_sum {
state $sum = 0;
state @numbers;
foreach my $number (@_) {
push @numbers, $number;
$sum += $number;
}
say "The sum of (@numbers) is $sum";
}
运行结果:
The sum of (5 6) is 11
The sum of (5 6 1 2 3) is 17
The sum of (5 6 1 2 3 4) is 21
- 不能在列表上下文中初始化数组和哈希类型的state变量(在Perl5.10中才有)
例:
state @array = qw/a b c/; # 这种写法是错误的
六、return操作符
- return用于从子程序中返回某个值
- 只有返回没有发生在最后一行代码时才需要使用return
- 只单独写一个return时,在标量上下文中返回值为undef,列表上下文中返回值为空列表
例:找出字符串在数组中的下标值
my @names = qw/a b c d e/;
my $result = &getIndex("c", @names);
sub getIndex {
my($what , @array) = @_;
foreach (0..$#array) { # 数组中所有元素的下标
if ($what eq $array[$_]) { # 字符串相等比较用eq
return $_; # 一找到就返回
}
}
-1; # 没有找到符合条件的元素返回-1,return在此处可有可无,省略此句则返回值为undef
}