商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > Perl中的子程序学习笔记

Perl中的子程序学习笔记

  发布于2026-06-29 阅读(0)

扫一扫,手机访问

在Perl中,子程序算得上是代码复用的基本功。它本质上就是一段独立的代码块,专门用来执行某个特定任务——好处很明显:减少重复代码,让整个程序结构更清晰、更易读。而且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 可以是一个列表。

四、局部变量
子程序内部的局部变量有两种定义方式:mylocal。区别在于作用域: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 会按逆序执行。

本文转载于:https://www.jb51.net/article/60774.htm 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

产品推荐

热门关注