在perl中的多个子例程调用中保留变量的值

时间:2015-02-08 05:28:31

标签: perl

只是想知道在对同一子程序的多次调用中保留变量值的最佳方法是什么。即

$someList  = &someRoutine(100, 200);
$someList2 = &someRoutine(100, 200);

sub someRoutine {
    $someAddition = 0;
    foreach $someSum (@_){
        $someAddition += $someSum;
    }
    return $someAddition
}

print $someList;
print $someList2;

基本上,someList应该打印300而someList2应该打印600.如何使someList2打印600?我希望在多个子程序调用中保留$ someAddition。

3 个答案:

答案 0 :(得分:5)

有几种方法可以做到这一点。我将展示其中两个:

首先,在现代版本的Perl中,您可以使用state

use feature qw/state/; 

print someRoutine(100,200), "\n";
print someRoutine(100,200), "\n";

sub someRoutine {
    state $someAddition = 0;
    foreach my $someSum ( @_ ) {
        $someAddition += $someSum;
    }
    return $someAddition;
}

在此版本中,$someAddition变量将初始化为零一次,且仅一次。从那时起,该值将在调用之间保留。

另一个版本使用词法闭包。这是一个例子:

my $summer = makeSummer();
print $summer->(100,200), "\n";
print $summer->(100,200), "\n";

sub makeSummer {
    my $someAddition = 0;
    return sub {
        $someAddition += $_ foreach @_;
        return $someAddition;
    }
}

第二个版本稍微复杂一点,但有两个优点。首先,您只需调用makeSummer例程来制作新的闭包即可开始新的求和。其次,它适用于任何版本的Perl 5,而不仅仅是最近版本足以拥有较新的state关键字的版本。

如果您不关心在声明sub之前初始化有状态变量,您也可以这样做:

my $someAddition;
sub someRoutine {
    $someAddition = 0 unless defined $someAddition;
    foreach my $someSum( @_ ) {
        $someAddition += $someSum;
    }
    return $someAddition;
}

第四种方法使用包全局变量。我将这个保存为最后一个,因为它最容易被滥用和犯错。但是你走了;

our $someAddition = 0;

someRoutine(100,200);
print "$someAddition\n";

someRoutine(100,200);
print "$someAddition\n";

sub someRoutine {
    $someAddition += $_ foreach @_;
}

在最后一个版本中,$someAddition是一个全局包,其全局范围使其可以在同一名称空间内的任何子例程内部和外部使用。

答案 1 :(得分:4)

  • 我假设您至少使用了Perl 5的变体?自二十两年前Perl 5的第一个版本以来,在子程序调用中使用&符号&是不好的做法。

  • 每个 Perl程序的顶部use strictuse warnings也是至关重要的,并声明您的变量是他们的第一个使用点{ {1}}。这是一个可以发现许多简单编码错误的措施,否则您很容易忽视这些错误。

  • Perl变量名称应仅使用小写字母,数字和下划线。大写字母保留用于全局标识符,例如包名称。

到目前为止,创建静态变量的最简单和最常见的方法就是在子例程之外声明它。喜欢这个

my

<强>输出

use strict;
use warnings;

my $some_list  = some_routine(100, 200);
my $some_list2 = some_routine(100, 200);

my $some_addition;

sub some_routine {
  $some_addition += $_ for @_;
  return $some_addition
}

print $some_list, "\n";
print $some_list2, "\n";

如果你想保护变量不被子程序以外的任何代码访问,那么只需将它们括在大括号中,就像这样

300
600

答案 2 :(得分:3)

在#34; man perlsub&#34;中查看Persistent Private Variables