我有一个脚本 ( A.pl) 和一个包 ( B.pm),我想在其中创建一个静态变量,B.pm以便A.pl.
use lib 'path/to/B_Package';
for loop 10 times {
fun(age);
}
if ($count>0) {
print "script fails";
}
Run Code Online (Sandbox Code Playgroud)
package B {
fun() {
my $age_given = shift;
my $count;
eval {
result = someFileHandling;
} or die {
$count++;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我会质疑这样的设计,下面提供了一些替代方案。
但是是的,它可以做到——声明为our可以通过其完全限定名称访问的变量。
在包文件Pack.pm 中
package Pack;
use warnings;
use strict;
use Exporter qw(import);
our @EXPORT_OK = qw(func);
our $count = 7;
sub func { ++$count }
1;
Run Code Online (Sandbox Code Playgroud)
并在其用户中
use warnings;
use strict;
use feature 'say';
use Pack qw(func);
for (1..2) {
func();
say "Current value of a global in 'Pack': ", $Pack::count;
}
$Pack::count = 123;
say "Current value of a global in 'Pack': ", $Pack::count;
Run Code Online (Sandbox Code Playgroud)
因此,在调用程序$count中Pack::func()可以看到对made in 的更改。更重要的是,$Pack::count可以通过解释器中的任何代码直接编写。
直接使用的包全局变量,$count如上所示,†是棘手的生物,难以明智地使用,但最终很容易被滥用。
一般来说,您不想要它们:它们的使用与将软件划分为通过明确定义的接口进行通信的组件的关键思想背道而驰,它们引入了不受控制的耦合,从而破坏了作用域等。在代码中使用这些变量的不同组件纠缠。
但是它们当然很有用并且在库中使用,主要用于常量和参数。
现在,让他们也改变?这可能会失控,尽管它也被用于图书馆(通过设置参数来控制他们的行为),但它更接近于“神级”的模拟,一个全能控制的实体。那时我会断然称它有缺陷和麻烦制造者。
为什么不让 subs 处理计数并返回更新的值?例如,他们可以使用statepragma保留值。或者甚至使用文件范围的变量,只要它是其业务内部的并且不允许外部人员戳它。
这是修订后的Pack.pm 中提到的两种方法的示例
package Pack;
use warnings;
use strict;
use feature qw(state);
use Exporter qw(import);
our @EXPORT_OK = qw(count func1 func2);
my $count = 7;
sub func1 { ++$count } # sets counter while doing its other work
sub count { # add check that input is numeric
$count += shift for @_; # Set count if values passed,
return $count; # return value in either case
}
sub func2 {
state $count = 0; # keeps count (its own $count)
return $count += shift // 1; # demo: add some and return
}
1;
Run Code Online (Sandbox Code Playgroud)
演示使用:
use warnings;
use strict;
use feature 'say';
use Pack qw(count func1 func2);
say "Call func2(), using 'state' feature, with its own counter: ";
for (1..2) { say "func2($_): ", func2($_) }
say '';
say "Set value for a file-wide counter, retrieve using count(): ";
for (1..2) { func1() }
say "Count is: ", count();
say "Use count() to set values as well: ";
for (1..2) { say "For #$_: ", count($_) }
Run Code Online (Sandbox Code Playgroud)
这打印
调用 func2(),使用 'state' 特性,使用它自己的计数器: 函数 2(1): 1 函数 2(2): 3 设置文件范围计数器的值,使用 count() 检索: 计数为:9 也可以使用 count() 来设置值: 与 1:10 2:12
下一步是将它变成一个类,然后您可以以非常自然的方式实现任何和所有类型的计数器。
有关变量的更多信息,请参阅这篇文章和这篇文章以及这篇Effective Perler 文章,作为初学者。
†一个our变量严格来说不是一个全球性的,但被混淆为包变量词汇(一个“真正的”全球!)具有相同的名称。