文章目录
一、子程序的定义、调用、返回
Perl中,子程序,即用户创建的函数。子程序的定义是全局性质的,不存在所谓的私有子程序。假如定义了两个同名的子程序,那么后面的子程序会覆盖掉前边的,如果启用了警告信息,Perl会告知子程序被重复定义。
- 定义:子程序由关键字sub、子程序名、以及花括号封闭起来的代码块组成。
- 调用:子程序的调用须在子程序名前加上&(与号)来调用它,当Perl无同名内置子函数时,与号也可以省略(一般不这么做)。
- 返回值:子程序被调用时一定是作为表达式的某一个部分,所有的子程序都有一个返回值,通常,最后一次执行的表达式结果(不管是什么)都会被自动当成子程序的返回值。
print "Hello\n";
sub marine{
$n += 1;
print "Hello, sailor number $n!\n"; #最后一次执行结果
}
&marine;
&marine;
$x = &marine; #可以多次调用
print $x; #返回1——表示最后的print语句成功执行
sub calc{
$a = $fred + $barney;
$b = $fred - $barney;
$c = $fred * $barney;
$d = $fred / $barney;
}
$fred = 30;
$barney = 3;
$result = &calc; #函数返回值——最后一次计算值10
print "$result\n";
编译运行:
Hello
Hello, sailor number 1!
Hello, sailor number 2!
Hello, sailor number 3!
1
10
二、默认参数列表@_
Perl子程序可以有参数,要传递参数到子程序里,只需要在调用的子程序名后边加上被括号圈引的列表表达式即可。例如:
$n = &max(10,15); #包含两个参数的子程序调用
默认数组变量@_:Perl会自动将传入的参数列表化名为数组变量@_。参数列表需要存储在某个数组变量里,好让子程序调用,而Perl便将这个数组称之为@_。@_变量实际上是子程序的私有变量。
#添加参数——默认数组:@_
sub max{ #参数在默认数组@_里,数组里的每一个参数,即$_[0],$_[1],...
if($_[0] > $_[1]){
$_[0];
}
else{
$_[1];
}
}
$result = &max(10,15);
print $result . "\n"; #输出15
三、私有变量与持久变量
3.1、my私有变量
默认情况下,Perl中的变量都是全局变量,也就是说,在程序的任何地方都可以访问他们,但是我们也可以借助my操作符来创建私有变量,也称词法变量。
- 适用范围:私有变量可以定义在任何语句块内,而不仅限于子程序语句块内。比如可在if、while、foreach语句块中使用。
- 作 用 域: 仅限于定义它的最内层语句块(或文件)。
- 上 下 文:my操作符并不会更改变量赋值时的上下文。
my($num1) = @_; #有括号——列表上下文,和($num1) = @_;相同,返回参数
my $num2 = @_; #无括号——标量上下文,和$num2 = @_;相同,返回数值
- 作用范围:在不加括号时,只能用来声明单个私有变量。
my $fred, $narney; #只声明了第一个为私有变量,第二个为普通全局变量
my ($fred, $barney); #声明了列表,两个都为私有变量
代码示例:
#定义私有变量——关键词my
sub max{ #允许定义同名函数,但是会覆盖原有的函数(相当于删除原有函数)
my($m, $n); #定义私有变量列表
($m,$n) = @_; #将默认参数赋值给私有变量
if($m > $n){ #可以简写成一行:if($m > $n){ $m }else{ $n }
$m; #最后一行的分号可以省略
}
else{
$n;
}
}
$result = &max(10,15);
print $result . "\n"; #输出15
#多个数比较取最大值
sub max {
my($max_number) = shift @_; #取出默认数组中的第一个参数
foreach(@_){ #循环——依次将默认数组@_中的剩余参数付给默认变量$_
if($_ > $max_number){
$max_number = $_;
}
}
$max_number; #函数最终返回值
}
$result = &max(12,18,26); #自动忽略多余的参数
print $result . "\n"; #打印:28
$maximum = &max(3,8,15,19,2);
print $maximum . "\n"; #打印:19
$result = &max(); #空参数赋值结果:undef
3.2、state持久变量
在子程序中使用my操作符定义的私有变量,在每次调用子程序时,私有变量都会被重新定义。而使用state操作符定义持久变量,可使子程序在多次调用期间保留变量之前的值,作用域依然局限于子程序内部。
说明:state声明持久变量的特性,是从Perl 5.010版本开始引入的。
代码示例:
#持久性的私有变量_state 5.010之后的版本之后引入
#比较私有变量与持久变量的不同
sub marine0{
my $k = 0; #私有变量
$k += 1;
print "Hello, sailor number $k\n";
}
&marine0;
&marine0;
&marine0;
sub marine1{
state $k = 0; #持久变量
$k += 1;
print "Hello, sailor number $k\n";
}
&marine1;
&marine1;
&marine1;
#定义数组为state
sub running_sum{
state $sum = 0;
state @numbers; #持久性数组
#state @array = qw(a,b,c); 不支持写法
foreach my $number(@_){ #默认参数数组@_
push @numbers, $number;
$sum += $number;
}
say "The sum of (@numbers) is $sum"; #变量与数组内插
}
&running_sum(5,6);
&running_sum(1..3);
&running_sum(4);
编译运行:
Hello, sailor number 1
Hello, sailor number 1
Hello, sailor number 1
Hello, sailor number 1
Hello, sailor number 2
Hello, sailor number 3
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
四、use strict编译指令
use strict编译指令:强制使用一些严格的、良好的编码风格。
从Perl 5.012版本开始,如果使用编译指令指定最低的Perl版本号的话,就相当于隐式打开约束指令:
use 5.012; #自动加载strict指令
strict编译指令含义:会要求声明事先所有新出现的变量,一般加上my操作符就可以了。也就是说,在使用变量时,尽可能的通过my进行声明。
my $bamm_bamm = 3; #新的词法变量,区别于语句块中的私有变量
习惯:在程序里加上use strict编译指令,对所有变量进行my预先声明。
五、return操作与返回类型(非标量)
5.1、return操作——结束子程序
return操作:立即停止执行并从子程序内返回某个值。
#关键字return_提前结束
my @names = qw/fred barney betty dino wilma betty/;
my $result = &find("betty", @names);
print "$result\n"; #打印索引:2
sub find {
my($what, @array) = @_;
foreach(0..$#array){ #对下标进行循环
if($what eq $array[$_]){
return $_; #一发现就提前返回下标值
}
}
-1; #不满足条件,函数返回-1
}
我们希望这个子程序能找出@names数组中betty元素的索引,先用my声明参数名:$what为要搜索的内容,@array为供搜索的目标数组。子程序find可以位于主代码的上边,也可位于下边。
5.2、非标量返回值
子程序不仅可以返回标量值,如果在列表上下文调用它,还可以返回列表值。
#函数返回非标量——数组
my $m ;
my $n ;
$m = 10;
$n = 20;
sub get_list{
if($m > $n){
$n..$m;
}
else{
reverse $m..$n;
}
}
my @c = &get_list;
print "@c\n"; #数组内插,不能单独打印数组。
编译运行:
20 19 18 17 16 15 14 13 12 11 10