子程序的定义
sub 子程序名{
子程序内容
}
子程序的调用
&子程序名
返回值
子程序中的最后一行即为返回值,如下示例:
$fred = 5 ;
$barney = 3 ;
sub sum_of_fred_and_barney {
print "Hey,you called the sum_of_fred_and_barney!\n" ;
$fred + $barney ; # 这就是返回值
}
$result=&sum_of_fred_and_barney; # 这里的 $result 的值为15
但如果sum_of_fred_and_barney子程序修改为:
参数
在定义子程序的时候可以不用显示的指出参数个数和类型,但是在调用的时候就一定要给出参数列表。这点与C\C++语言就有些不同了
如下:
if ( $_ [ 0 ] > $_ [ 1 ] ) {
$_ [ 0 ] ;
} else {
$_ [ 1 ] ;
}
}
上面这段代码中需要注意的是子程序的参数列表。默认情况下参数列表是属于 @_ 数组的,那么$_[0]就代表第一个元素也就是第一个参数,$_[1] 就是第二个参数。
$n = &max(4,5);
这时$n为5
那如果 $n = &max(4,5,6);
这样的话多余的参数会被忽略——反正子程序也不会用到$_[2],所以Perl并不在乎里面是否有值。参数如果不足也会被忽略——如果用到超出@_数组边界的参数,只会得到undef。
子程序中的私有变量
既然每次调用子程序是Perl都会给我们新的@_,难道不能让他产生私有变量吗?当然可以了!
默认情况下Perl中所有的变量都是全局变量。但如果在定义变量的前面使用my操作符的话,这个变量就变成了私有变量。
如下例子:
my ( $m , $n ) = @_ ;
if ( $m > $n ) { $m ; } else { $n ; }
}
$m与$n的作用范围只在max子程序内,在程序其他部分的相应变量不会受到子程序变量的影响。反之,别的程序代码也无法访问或修改这些私有变量。
长度可变的参数列表
在真实的Perl代码中,尝尝把更长的(任意长度的)列表作为参数传给子程序。当然,子程序可以很容易的通过检查@_数组的长度来确定参数的个数是否正确。比方说我们可以将max函数完善一下检查参数列表:
if ( @_ != 2 ) {
print "WARNING!&max should get exactly to arguments!\n" ;
}
my ( $m , $n ) = @_ ;
if ( $m > $n ) { $m ; } else { $n ; }
}
更好的&max子程序
sub max {
my ( $max_so_far ) = shift @_ ; # 数组中的第一个值暂时把它当成最大值
foreach ( @_ ) { # 遍历数组@_ 中的其他元素
if ( $_ > $max_so_far ) { # 判断当前的元素是否比$max_so_far还大
$max_so_far = $_ ;
}
}
$max_so_far ;
}
$maximum = &max ( 3 , 4 , 5 , 6 , 7 ) ;
空参数列表
上文的&max函数即使超过2个参数,修改后的&max也可以应付,但如果一个参数都没有呢?这听起来似乎有些杞人忧天。毕竟,怎么可能会有人调用&max却不传入任何参数呢?但是,也许会有人写出如下的程序代码:
$maximum = &max(@numbers);
某些时候,数组@numbers或许是一个空的列表。也许数组中的内容是程序从文件里读入的,但文件却是空的。那么这种情况&max会怎么样呢?
子程序的第一行会对参数组@_(现在是空的)进行shift操作,以此作为$max_so_far的值。这并不会出错,因为数组是空的。所以shift会返回undef给$max_so_far
现在foreach循环要遍历@_数组,但是由于@_是空的,所以循环本身不会被执行。
接下来,perl将$max_so_far的值undef作为子程序的返回值。从某种角度来看,那是正确的结果,因为在空列表中没有最大的值。
关于语法(my)变量
事实上,词法变量可使用在任何语句块内,而不仅限于子程序的语句块。如if、while或foreach
每当我们谈到my()操作符是,请注意,在my不适用括号时,只用来声明单个词法变量如:
my $fred,$barney; # 错!没声明 $barney
my ($fred,$barney); # 两个都声明了
当然,也可以使用my来创建新的私有数组
my @phone_number;
所有新的变量的值一开始都是空的;标量被设为undef,数组被设为空列表。
use strict编译命令
所谓编译命令,就是对编译器的指示,告诉它关于程序代码的一些信息。这会让perl语法编译器强制执行一些严格的、确保良好程序设计的规则。
根据大部分人的建议,比整个屏幕长的程序都应该加上use strict
return 操作符
return操作符会从子程序中立即返回某个值:
输出结果为:
1
省略调用子程序时使用的&符号
有两种情况可以省略这个符号
情况1:调用子程序时使用的参数在括号内
my @cards = shuffle(@deck_of_cards); # shuffle 前没有必要用&
情况2:子程序的定义在调用之前
sub division{
$_[0] / $_[1];
}
my $quotient = division 355,113; # 这里甚至连括号都省略了。呵呵
特殊情况:当自己定义的子程序与Perl内置的函数同名时。如果少了&符号,就算我们已经定义了子程序&chomp,仍然会调用到内置函数chomp。
因此,真正的省略规则如下:
你知道所有Perl的内置函数名
非标量返回值
子程序不仅可以返回标量值,如果在列表上下文中调用它,他就能返回列表值。如下代码:
输出结果:
11 10 9 8 7 6
持久性私有变量
说白了就是在子程序中的私有变量,但是这个私有变量在每次调用子程序时不会重新初始化。使用state操作符来定义持久性私有变量。
state $n = 0 ; # private, persistent variable $n
$n += 1 ;
print "Hello, sailor number $n!\n" ;
}