第6章 子过程:
像其他的语言一样,Perl也支持自定义的子过程。(注:我们也把它们叫做函数,不过函数和子过程在perl里一样的东西。
有时候我们甚至叫它们方法,方法和函数或子过程是同样的方式定义的,只是调用方式不同)
1.0 语法:
声明一个命名子过程,但不定义它,使用下面的形式:
sub NAME
sub NAME PROTO
sub NAME ATTRS
sub NAME PROTO ATTRS
声明并且定义一个命名子过程,加上一个{};
对于没有NAME的形式,你还必须提供调用子过程的方法,因此你必须保存返回值,因为这种形式的sub声明方法不但在编译的时候编译,
同时也产生一个允许时的返回值,所以我们就可以保证保存它:
[root@master big]# cat a1.pl
use Data::Dumper;
$subref= sub { return aa};
my $xx= Dumper($subref);
print "111111111
";
print $xx;
print "
";
print "222222222222
";
print $subref;
print "
";
print "3333333333
";
$yy=&$subref();
print $yy;
print "
";
[root@master big]# perl a1.pl
111111111
$VAR1 = sub { "DUMMY" };
222222222222
CODE(0xcdf350)
3333333333
aa
use base qw(
Weixin::Message
Weixin::Client::Callback
Weixin::Client::Operate
Weixin::Client::Friend
Weixin::Client::Chatroom
Weixin::Client::Request
Weixin::Client::Cron
Weixin::Client::Plugin
Weixin::Client::Base
);
use MODULE qw(NAME1 NAME2 NAME2...)
直接调用子过程可以用下面的方法:
1.NAME(LIST) ##有圆括号时&是可选的
2.NAME LIST #如果预声明/输入了子过程,那么圆括弧是选的
3. &$subref ##把当前的@_输出到该子过程
2.0 语意:
在你记住所有语法前,你只需要记住下边这种定义子过程的普通方法:
[root@master big]# cat a2.pl
sub razzle{
print "Ok,you've been razzled.
";
}
razzle();
[root@master big]# perl a2.pl
Ok,you've been razzled.
现在,如果你将设计一种可以支持不定数量的任意参数的语言,你最好让你的语言在处理这些任意长的参数列表上容易些,
所有传入Perl过程的参数都是以@_身份传入的。 如果你调用一个有两个参数的函数,它们在函数内部可以作为@_数组的前两个成员访问:
$_[0] 和$_[1]
子过程(其他的程序块也一样)的返回值是过程最后一个表达式的只,或者你可以在子过程的任何一个地方明确使用一个return
语句来返回值并且退出子过程
[root@master big]# cat a1.pl
use Data::Dumper;
$subref= sub { return aa;print "bb
"};
$yy=&$subref;
print $yy;
print "
";
[root@master big]# perl a1.pl
aa
[root@master big]# cat a3.pl
sub test {
$a = shift;
$b = shift;
$c = shift;
return $a + $b + $c;
};
$xx=test(1,2,3);
print "$xx
";
[root@master big]# perl a3.pl
6
2.2 错误提示
[root@master big]# cat a3.pl
sub test {
$a = shift;
$b = shift;
eval {return $a / $b} ;
if ($@){return aaaaaaaa}else{return bbbbbbbbbb};
};
$xx=test(9,3);
print "$xx
";
[root@master big]# perl a3.pl
bbbbbbbbbb
[root@master big]# cat a3.pl
sub test {
$a = shift;
$b = shift;
eval {return $a / $b} ;
if ($@){return aaaaaaaa}else{return bbbbbbbbbb};
};
$xx=test(9,0);
print "$xx
";
[root@master big]# perl a3.pl
aaaaaaaa
3.0 传入引用:
这里有几个简单的例子,首先,让我们定义一个函数,这个函数使用数组的引用作为参数,当这个数组非常大时,作为一个引用传递
要比传入一长列值要快的多:
[root@master big]# cat a4.pl
sub sum {
my $aref = shift;
print "@ref is @$aref
";
foreach (@$aref) {$total += $_};
return $total;
};
my @a=(1, 4, 7);
$xx = sum(@a);
print $xx;
print "
";
print "$total is $xx
";
[root@master big]# perl a4.pl
@ref is 1 4 7
12
$total is 12
4.0 函数原型
Perl 可以让你定义你自己的函数,这些函数可以像Perl的内建函数一样调用,例如 push(@array,$item);
4.1 内联常量函数:
带有() 的函数原型表示这个函数没有任何参数,就像内建函数time一样
[root@master big]# cat a5.pl
sub PI () { 4 * atan2(1, 1) } ;
$xx=&PI();
print "$xx is $xx
";
[root@master big]# perl a5.pl
$xx is 3.14159265358979
[root@master big]#
5.0 子过程属性