Perl学习笔记(6)-函数设计

Perl的函数

Perl函数也叫子程序,就是用户定义的函数。为了方便,我一律称为函数,不称子程序。Perl函数的语法格式如下所示:

1
2
3
sub subroutine{
statements;
}

调用函数的语法格式为subroutine( 参数列表 ),如下所示:

1
2
3
4
sub Hello{
print "Hello, World!\n";
}
Hello();

由于在设计Hello函数时,并没有设计相应的参数,因此在运行时就不需要加参数,但是还需要加上括号。

向函数传递参数

Perl 函数可以和其他编程语言一样接受多个参数,函数参数使用特殊数组@_标明。因此函数第一个参数为_[0], 第二个参数为_[1], 以此类推,用户可以通过改变@_数组中的值来改变相应实际参数的值。。不论参数是标量型还是数组型的,用户把参数传给函数时,perl默认按引用的方式调用它们,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
biotest@ubuntu:~/perl/05function$ cat function_parameter.pl
#!/usr/bin/perl
sub mean{
$n = scalar(@_);
$sum = 0;
foreach $item(@_){
$sum = $sum + $item;
}
$average = $sum/$n;
print 'Input parameter is : ',"@_\n";
print "The first parameter is $_[0]\n";
print "The average of inputed parameters is $average\n";
}
mean(10, 20, 30);
biotest@ubuntu:~/perl/05function$ perl function_parameter.pl
Input parameter is : 10 20 30
The first parameter is 10
The average of inputed parameters is 20

代码解释:scalar不是求元素个数,它用来产生一个标量环境,对数组进行操作时,会返回元素个数。$n = scalar(@_)就是获取所有传入的参数的个数,在这段代码中,n值就是3。

向函数传递列表

由于@_变量是一个数组,所以它可以向函数中传递列表。但如果我们需要传入标量和数组参数,需要把列表放在最后一个参数上,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
biotest@ubuntu:~/perl/05function$ cat print_list.pl
#!/usr/bin/perl
sub PrintList{
my @list = @_;
print "List is @list\n";
}
$a = 10;
@b = (1, 2, 3, 4);
PrintList($a, @b);
biotest@ubuntu:~/perl/05function$ perl print_list.pl
List is 10 1 2 3 4

向函数传递哈希

当向函数传递哈希表时,它将复制到@_中,哈希表将被展开为键/值组合的列表,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
biotest@ubuntu:~/perl/05function$ cat print_hash.pl
#!/usr/bin/perl
sub PrintHash{
my(%hash) = @_;
foreach my$key (keys %hash){
my $value =$hash{$key};
print "$key:$value\n";
}
}
%hash = ('name' => 'Baidu', 'age' =>11);
PrintHash(%hash);
biotest@ubuntu:~/perl/05function$ perl print_hash.pl
name:Baidu
age:11

函数返回值

函数可以向其他编程语言一样使用retur 语句来返回函数值。如果没有使用return语句,则函数的最后一行语句将作为返回值,如下所示:

1
2
3
4
5
6
7
8
9
biotest@ubuntu:~/perl/05function$ cat return.pl
#!/usr/bin/perl
sub add_a_b{
$_[0] + $_[1];
}
print add_a_b(1,12)."\n";
biotest@ubuntu:~/perl/05function$ perl return.pl
13

函数的局部变量

默认情况下,Perl 中所有的变量都是全局变量,这就是说变量在程序的任何地方都可以调用。如果我们需要设置私有变量(私有变量其实与其他编程语言中的局部变量是一样的,后文一律称为局部变量),可以使 my操作符来设置。my操作符用于创建作用域变量,通过my创建的变量,存活于声明开始的地方,直到闭合作用域的结尾。闭合作用域指的可以是一对花括号中的区域,可以是一个文件,也可以是一个if, while, for, foreach, eval字符串。它的用法如下所示:

1
2
3
4
sub somefunc {
my $variable; # $variable在函数somefunc()之外不可见
my ($another, @an_array, %a_hash); # 同时声明多个变量
}

以下案例就演示了如何声明一个或多个局部变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
biotest@ubuntu:~/perl/05function$ cat local_variable.pl
#!/usr/bin/perl
$variable_global = "Hello, World!\n";
sub PrintHello{
my $variable_global;
$variable_global = "Hello, Learner!\n";
print "Strings in function is :$variable_global\n";
}
PrintHello();
print "Strings beyond function is : $variable_global\n";
biotest@ubuntu:~/perl/05function$ perl local_variable.pl
Strings in function is :Hello, Learner!
Strings beyond function is : Hello, World!

变量的临时赋值

我们可以使用 local 为全局变量提供临时的值,在退出作用域后将原来的值还回去。local定义的变量不存在于主程序中,但存在于该函数和该函数调用的函数中。定义时可以给其赋值,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
biotest@ubuntu:~/perl/05function$ cat local_temp.pl
#!/usr/bin/perl
$variable_global = "Hello, World!\n";
sub PrintLocal{
local $variable_global;
$variable_global = "Hello, Learner!\n"; #临时赋值
PrintMe();
print "PrintLocal function has strings: $variable_global\n";
}
sub PrintMe{
print "PrintMe function has strings: $variable_global\n";
}
sub PrintHello{
print "PrintHello function has strings: $variable_global\n";
}
PrintLocal();
PrintHello();
print "Strings beyond function is : $variable_global\n";
biotest@ubuntu:~/perl/05function$ perl local_temp.pl
PrintMe function has strings: Hello, Learner!
PrintLocal function has strings: Hello, Learner!
PrintHello function has strings: Hello, World!
Strings beyond function is : Hello, World!

静态变量

state关键字将局部变量永久存在。state也是词法变量,所以只在定义该变量的词法作用域中有效,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
biotest@ubuntu:~/perl/05function$ cat state.pl
#!/usr/bin/perl
use feature 'state';
sub PrintCount{
state $count = 0;
print "counter value is : $count\n";
$count++;
}
for (1..5){
PrintCount();
}
biotest@ubuntu:~/perl/05function$ perl state.pl
counter value is : 0
counter value is : 1
counter value is : 2
counter value is : 3
counter value is : 4

注1:state仅能创建闭合作用域为函数内部的变量。
注2:state是从Perl 5.9.4开始引入的,所以使用前必须加上 use。
注3:state可以声明标量、数组、哈希。但在声明数组和哈希时,不能对其初始化(至少Perl 5.14不支持)。

函数调用上下文

函数调用过程中,会根据上下文来返回不同类型的值,比如localtime()函数,在标量上下文返回字符串,在列表上下文返回列表,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
biotest@ubuntu:~/perl/05function$ cat function_context.pl
#!/usr/bin/perl
my $variable = localtime(time);
print $variable;
print "\n";
($sec,$min,$hour,$mday,$mon, $year,$wday,$yday,$isdst) = localtime(time);
printf("%d-%d-%d %d:%d:%d\n",$year+1990,$mon+1,$mday,$hour,$min,$sec);
biotest@ubuntu:~/perl/05function$ perl function_context.pl
Fri May 18 16:53:48 2018
2108-5-18 16:53:48

参考资料

Perl教程|菜鸟教程