参数与返回值 #

一、参数详解 #

1.1 @_ 数组 #

所有参数存储在 @_ 中:

perl
sub show_args {
    print "Number of args: " . @_ . "\n";
    print "Args: @_\n";
}

show_args("a", "b", "c");

1.2 直接访问参数 #

perl
sub add {
    return $_[0] + $_[1];
}

print add(3, 5);

1.3 shift获取参数 #

perl
sub greet {
    my $name = shift;
    print "Hello, $name!\n";
}

greet("Tom");

1.4 多参数解包 #

perl
sub process {
    my ($first, $second, @rest) = @_;
    
    print "First: $first\n";
    print "Second: $second\n";
    print "Rest: @rest\n";
}

process(1, 2, 3, 4, 5);

1.5 哈希参数 #

perl
sub create_person {
    my %args = @_;
    
    print "Name: $args{name}\n";
    print "Age: $args{age}\n";
}

create_person(
    name => "Tom",
    age  => 25,
);

二、默认参数 #

2.1 使用 || 或 // #

perl
sub greet {
    my $name = shift // "World";
    print "Hello, $name!\n";
}

greet();
greet("Tom");

2.2 使用条件 #

perl
sub connect {
    my %args = (
        host => "localhost",
        port => 3306,
        @_,
    );
    
    print "Connecting to $args{host}:$args{port}\n";
}

connect();
connect(port => 3307);
connect(host => "192.168.1.1", port => 5432);

2.3 命名参数默认值 #

perl
sub configure {
    my %args = @_;
    
    my $host = $args{host} // "localhost";
    my $port = $args{port} // 80;
    my $debug = $args{debug} // 0;
    
    print "Host: $host, Port: $port, Debug: $debug\n";
}

configure(debug => 1);

三、上下文 #

3.1 标量上下文 vs 列表上下文 #

perl
my @arr = localtime();
my $scalar = localtime();

print "List: @arr\n";
print "Scalar: $scalar\n";

3.2 wantarray #

检测调用上下文:

perl
sub get_data {
    if (wantarray) {
        return (1, 2, 3, 4, 5);
    } else {
        return 5;
    }
}

my @list = get_data();
my $count = get_data();

print "List: @list\n";
print "Count: $count\n";

3.3 实际应用 #

perl
sub file_lines {
    my $file = shift;
    open my $fh, "<", $file or return;
    
    if (wantarray) {
        return <$fh>;
    } else {
        local $/;
        return <$fh>;
    }
}

my @lines = file_lines("test.txt");
my $content = file_lines("test.txt");

四、引用参数 #

4.1 传递数组引用 #

perl
sub process_array {
    my $arr_ref = shift;
    
    foreach my $item (@$arr_ref) {
        print $item . "\n";
    }
}

my @data = (1, 2, 3, 4, 5);
process_array(\@data);

4.2 传递哈希引用 #

perl
sub show_person {
    my $person = shift;
    
    print "Name: $person->{name}\n";
    print "Age: $person->{age}\n";
}

my %tom = (name => "Tom", age => 25);
show_person(\%tom);

4.3 修改参数 #

perl
sub increment {
    my $ref = shift;
    $$ref++;
}

my $count = 0;
increment(\$count);
increment(\$count);
print $count;

4.4 原地修改数组 #

perl
sub double_values {
    my $arr = shift;
    $_ *= 2 foreach @$arr;
}

my @nums = (1, 2, 3, 4, 5);
double_values(\@nums);
print "@nums\n";

五、返回引用 #

5.1 返回数组引用 #

perl
sub get_numbers {
    my @arr = (1, 2, 3, 4, 5);
    return \@arr;
}

my $nums = get_numbers();
print "@$nums\n";

5.2 返回哈希引用 #

perl
sub create_person {
    my ($name, $age) = @_;
    return {
        name => $name,
        age  => $age,
    };
}

my $person = create_person("Tom", 25);
print "Name: $person->{name}\n";

5.3 返回子程序引用 #

perl
sub create_counter {
    my $count = 0;
    return sub {
        return ++$count;
    };
}

my $counter = create_counter();
print $counter->() . "\n";
print $counter->() . "\n";
print $counter->() . "\n";

六、原型 #

6.1 基本原型 #

perl
sub my_push (\@@) {
    my $arr = shift;
    push @$arr, @_;
}

my @arr;
my_push @arr, 1, 2, 3;
print "@arr\n";

6.2 常用原型 #

原型 说明
$ 标量
@ 数组
% 哈希
& 子程序
* 类型通配符
\ 引用
perl
sub run_code (&) {
    my $code = shift;
    $code->();
}

run_code { print "Hello!\n" };

6.3 不推荐使用原型 #

现代Perl推荐避免使用原型,除非有特殊需求。

七、实践练习 #

练习1:灵活参数 #

perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;

sub search {
    my %opts = (
        pattern => "",
        case_sensitive => 0,
        @_,
    );
    
    my $text = shift // "";
    
    my $pattern = $opts{pattern};
    my $flags = $opts{case_sensitive} ? "" : "i";
    
    my @matches = $text =~ /($pattern)/$flags;
    return @matches;
}

my $text = "Hello Perl World";
my @matches = search($text, pattern => "perl", case_sensitive => 0);
say "Matches: @matches";

练习2:上下文感知函数 #

perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;

sub range {
    my ($start, $end) = @_;
    
    if (wantarray) {
        return ($start..$end);
    } else {
        return $end - $start + 1;
    }
}

my @numbers = range(1, 10);
my $count = range(1, 10);

say "Numbers: @numbers";
say "Count: $count";

练习3:回调函数 #

perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;

sub process_items {
    my ($items, $callback) = @_;
    
    my @results;
    foreach my $item (@$items) {
        push @results, $callback->($item);
    }
    return @results;
}

my @numbers = (1, 2, 3, 4, 5);

my @doubled = process_items(\@numbers, sub {
    my $n = shift;
    return $n * 2;
});

my @squared = process_items(\@numbers, sub {
    my $n = shift;
    return $n ** 2;
});

say "Original: @numbers";
say "Doubled: @doubled";
say "Squared: @squared";

八、总结 #

本章学习了:

  • 参数传递详解
  • 默认参数
  • 上下文感知(wantarray)
  • 引用参数
  • 返回引用
  • 原型

下一章将学习作用域与闭包。

最后更新:2026-03-27