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函数执行成功之意
}

参数

在定义子程序的时候可以不用显示的指出参数个数和类型,但是在调用的时候就一定要给出参数列表。这点与C\C++语言就有些不同了
如下:

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却不传入任何参数呢?但是,也许会有人写出如下的程序代码:

$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操作符会从子程序中立即返回某个值:

#!/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 "$result\n" ;

输出结果为:
1

省略调用子程序时使用的&符号

有两种情况可以省略这个符号

情况1:调用子程序时使用的参数在括号内
my @cards = shuffle(@deck_of_cards); # shuffle 前没有必要用&

情况2:子程序的定义在调用之前
sub division{
$_[0] / $_[1];
}

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 " @c\n"

输出结果:
11 10 9 8 7 6

持久性私有变量

说白了就是在子程序中的私有变量,但是这个私有变量在每次调用子程序时不会重新初始化。使用state操作符来定义持久性私有变量。

sub marine {
state $n = 0 ; # private, persistent variable $n
$n += 1 ;
print "Hello, sailor number $n!\n" ;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值