Perl笔记:03、子程序
子程序的定义sub 子程序名{ 子程序的调用&子程序名 返回值子程序中的最后一行即为返回值,如下示例:
#!/usr/bin/perl -w
$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子程序修改为:
sub sum_of_fred_and_barney
{
print "Hey,you called the sum_of_fred_and_barney!n" ; $fred + $barney ; print "Hey,I'm returning a value now!n" ; # 这里会给出结果1,也就是print函数执行成功之意 } 参数 在定义子程序的时候可以不用显示的指出参数个数和类型,但是在调用的时候就一定要给出参数列表。这点与CC++语言就有些不同了
sub max
{
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操作符的话,这个变量就变成了私有变量。
sub max
{
my ( $m , $n ) = @_ ; if ( $m > $n ) { $m ; } else { $n ; } } $m与$n的作用范围只在max子程序内,在程序其他部分的相应变量不会受到子程序变量的影响。反之,别的程序代码也无法访问或修改这些私有变量。 长度可变的参数列表在真实的Perl代码中,尝尝把更长的(任意长度的)列表作为参数传给子程序。当然,子程序可以很容易的通过检查@_数组的长度来确定参数的个数是否正确。比方说我们可以将max函数完善一下检查参数列表:
sub max
{
if ( @_ != 2 ) { print "WARNING!&max should get exactly to arguments!n" ; } my ( $m , $n ) = @_ ; if ( $m > $n ) { $m ; } else { $n ; } } 更好的&max子程序
#!/usr/bin/perl -w
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却不传入任何参数呢?但是,也许会有人写出如下的程序代码:
某些时候,数组@numbers或许是一个空的列表。也许数组中的内容是程序从文件里读入的,但文件却是空的。那么这种情况&max会怎么样呢? 子程序的第一行会对参数组@_(现在是空的)进行shift操作,以此作为$max_so_far的值。这并不会出错,因为数组是空的。所以shift会返回undef给$max_so_far 现在foreach循环要遍历@_数组,但是由于@_是空的,所以循环本身不会被执行。 接下来,perl将$max_so_far的值undef作为子程序的返回值。从某种角度来看,那是正确的结果,因为在空列表中没有最大的值。 关于语法(my)变量事实上,词法变量可使用在任何语句块内,而不仅限于子程序的语句块。如if、while或foreach 每当我们谈到my()操作符是,请注意,在my不适用括号时,只用来声明单个词法变量如: 当然,也可以使用my来创建新的私有数组
所有新的变量的值一开始都是空的;标量被设为undef,数组被设为空列表。 use strict编译命令所谓编译命令,就是对编译器的指示,告诉它关于程序代码的一些信息。这会让perl语法编译器强制执行一些严格的、确保良好程序设计的规则。 根据大部分人的建议,比整个屏幕长的程序都应该加上use strict return 操作符return操作符会从子程序中立即返回某个值:
#!/usr/bin/perl -w
use strict ; my @names = qw/zyq wcl zsc pf fyr zyz/ ; sub which_element_is { my ( $what , @array ) = @_ ; foreach ( 0 .. $#array ) { if ( $what eq $array [ $_ ] ) { return $_ ; } } - 1 ; } my $result = &which_element_is ( "wcl" , @names ) ; print "$resultn" ; 输出结果为: 省略调用子程序时使用的&符号有两种情况可以省略这个符号 情况1:调用子程序时使用的参数在括号内 情况2:子程序的定义在调用之前 my $quotient = division 355,113; # 这里甚至连括号都省略了。呵呵 特殊情况:当自己定义的子程序与Perl内置的函数同名时。如果少了&符号,就算我们已经定义了子程序&chomp,仍然会调用到内置函数chomp。 因此,真正的省略规则如下: 你知道所有Perl的内置函数名 非标量返回值子程序不仅可以返回标量值,如果在列表上下文中调用它,他就能返回列表值。如下代码:
#!/usr/bin/perl -w
use strict ; my ( $fred , $barney ) = ( 11 , 6 ) ; sub list_from_fred_to_barney { if ( $fred < $barney ) { $fred .. $barney ; } else { reverse $barney .. $fred ; } } my @c = &list_from_fred_to_barney ; print " @cn" 输出结果: 持久性私有变量说白了就是在子程序中的私有变量,但是这个私有变量在每次调用子程序时不会重新初始化。使用state操作符来定义持久性私有变量。
sub marine
{
state $n = 0 ; # private,persistent variable $n $n += 1 ; print "Hello,sailor number $n!n" ; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |