发布于2026-06-29 阅读(0)
扫一扫,手机访问
在Perl中,子程序算得上是代码复用的基本功。它本质上就是一段独立的代码块,专门用来执行某个特定任务——好处很明显:减少重复代码,让整个程序结构更清晰、更易读。而且Perl对子程序的定义位置很宽容,几乎可以放在程序的任何地方。定义方式也特别简洁:

一、定义
函数分为系统函数和用户函数。子程序即执行一个特殊任务的一段分离的代码,它可以使减少重复代码且使程序易读。PERL中,子程序可以出现在程序的任何地方。定义方法为:
sub subroutine{
statements;
}
二、调用
调用方式有好几种,这里逐一拆解:
1. 用 & 调用
最传统的方式,不管子程序定义在前还是后,直接加 & 符号就能调用。
&subname;
...
sub subname{
...
}
2. 先定义后调用,可以省略 & 符号
如果子程序在调用之前已经定义好了,那么直接写子程序名即可。建议采用这种方式,看起来更清爽。
sub subname{
...
}
...
subname;
3. 前向引用
先声名子程序的名字,后面再定义具体内容。这种手法适用于某些需要提前声明的场景。
sub subname;
...
subname;
...
sub subname{
...
}
4. 用 do 调用
do my_sub(1, 2, 3); 等价于 &my_sub(1, 2, 3);,写法上更接近函数式风格。
三、返回值
默认情况下,子程序中最后一个语句的值会被当作返回值返回。当然你也可以用 return (retval); 明确退出并返回某个值,retval 可以是一个列表。
四、局部变量
子程序内部的局部变量有两种定义方式:my 和 local。区别在于作用域:my 定义的变量只存在于当前子程序内部;local 定义的变量则不仅存在于当前子程序,还会传递到该子程序所调用的子程序中(Perl 4 没有 my)。定义时可以顺便赋值:
my($scalar) = 43;
local(@array) = (1, 2, 3);
五、子程序参数传递
1. 基本形式
调用时直接传入标量或列表,子程序内部通过 @_ 数组接收参数:
&sub1(&number1, $number2, $nubmer3);
...
sub sub1{
my($number1, $number2, $number3) = @_;
...
}
2. 传送数组
可以直接传入整个数组,子程序内部用 my (@list) = @_; 接收。不过要注意,如果同时传入两个数组,第二个数组会为空——因为子程序只会把 @_ 中的所有元素赋给第一个数组变量:
&addlist (@mylist);
&addlist ("14", "6", "11");
&addlist ($value1, @sublist, $value2);
...
sub addlist {
my (@list) = @_;
...
}
但简单变量和数组变量可以混合传递:
&twoargs(47, @mylist); # 47赋给$scalar,@mylist赋给@list
&twoargs(@mylist); # @mylist的第一个元素赋给$scalar,其余赋给@list
...
sub twoargs {
my ($scalar, @list) = @_;
...
}
六、递归子程序
Perl 的子程序可以互相调用,当然也可以调用自身——这就是递归。递归子程序需要满足两个条件:第一,除了那些不被子程序改变的变量外,所有变量必须是局部的;第二,子程序内部必须有停止调用自身的出口条件。
七、用别名传递数组参数
前面用 &my_sub(@array) 的方式会把整个数组拷贝到 @_ 中,当数组很大时,这种拷贝很消耗资源。别名传递则直接操作原始数组,不做拷贝,效率高得多。
1. 基本用法
在子程序定义时接收一个类型团(typeglob),然后通过别名直接操作原数组:
@myarray = (1, 2, 3, 4, 5);
&my_sub(*myarray);
sub my_sub {
my (*subarray) = @_;
}
2. 注意副作用
这种方式类似于 C 语言传递数组指针,但略有不同。由于别名会同时影响同名的标量变量,如果存在同名简单变量,操作别名时该变量也会被修改:
$foo = 26;
@foo = ("here's", "a", "list");
&testsub (*foo);
...
sub testsub {
local (*printarray) = @_;
...
$printarray = 61;
}
当子程序执行完后,主程序中的 $foo 不再是 26,而变成了 61。这一点需要格外留意。
3. 传递多个数组
别名机制还有一个好处:可以同时传递多个数组:
@array1 = (1, 2, 3);
@array2 = (4, 5, 6);
&two_array_sub (*array1, *array2);
sub two_array_sub {
my (*subarray1, *subarray2) = @_;
}
在子程序内部,subarray1 就是 array1 的别名,subarray2 就是 array2 的别名。
八、预定义的子程序
Perl 5 预定义了三个特殊子程序,它们在特定时刻自动执行:
BEGIN 子程序在程序启动时被调用。END 子程序在程序结束时被调用。AUTOLOAD 子程序在找不到某个子程序时被调用。你可以自定义它们来执行特定动作:
BEGIN {
print("Hi! Welcome to Perl!\n");
}
AUTOLOAD{
print("subroutine $AUTOLOAD not found\n"); # $AUTOLOAD 即未找到的子程序名
print("arguments passed: @_\n");
}
如果同一个预定义子程序定义了多个,BEGIN 会按定义顺序执行,而 END 会按逆序执行。
下一篇:Perl中的控制结构学习笔记
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8