我会质疑这样的设计,下面提供了一些替代方案。
但是可以做到——声明为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;
在它的用户中
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;
所以在调用程序中可以看到在Pack::func() 中对$count 所做的更改。更重要的是,$Pack::count 可以直接由解释器中的任何代码编写。
打算直接使用的包全局变量,如上面的$count,† 是棘手的生物,很难合理使用,但很容易最终被滥用。
一般而言,您不希望它们:它们的使用与将软件划分为通过明确定义的接口进行通信的组件中的关键思想背道而驰,它们引入了不受控制的耦合,从而破坏了范围等。使用这些变量时,不同的组件在代码中纠缠不清。
但它们当然很有用,并且在库中使用,主要用于常量和参数。
现在,让它们也改变吗?这可能会失控,尽管 也用于库中(通过设置参数来控制它们的行为),但它更接近于“上帝类”的类似物,一个全——控制实体。那时我会直截了当地称其为有缺陷和麻烦制造者。
为什么不让 subs 处理计数并返回更新的值?例如,他们可以使用 state pragma 保留值。或者甚至使用文件范围的变量,只要它是其业务内部的,并且不允许外人戳它。
这是修订后的 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;
使用演示:
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($_) }
打印出来
调用 func2(),使用“状态”功能,并带有自己的计数器:
函数2(1):1
函数2(2):3
为文件范围的计数器设置值,使用 count() 检索:
计数是:9
也可以使用 count() 来设置值:
1:10
2:12
下一步是把它变成一个类,然后你就可以用非常自然的方式实现任何类型的计数器了。
有关变量的更多信息,请参阅this post 和this post 以及此Effective Perler article,供初学者参考。
† 严格来说,our 变量不是全局变量,而是一个别名为包变量的词法(“真正的”全局变量!)同名。