我有两个模块:test1和test2,我需要按顺序运行它们的子程序。他们需要修改相同的变量$ var,外部脚本需要打印最终结果。遗憾的是,这不起作用,似乎与此S.O. Question非常相似。
#test1.pm
use strict;
package test1;
my $var;
sub step1 {
$var = "Hello";
}
1;
#test2.pm
use strict;
package test2;
my $var;
sub step1 {
$var = $var." World!\n";
}
1;
#execTests.pl
use strict;
require test1;
require test2;
&test1::step1;
&test2::step1;
print $test2::var;
如何将$ var包含在两个必需包的相同范围内?
答案 0 :(得分:1)
AFAIK不可能让两个变量始终共享相同的值。以下是一些可以帮助您的想法:
{
package test1;
our $var;
sub step1 {$var = "Hello"}
}
{
package test2;
our $var;
sub step1 {$var .= " World!\n"}
}
test1::step1();
$test2::var = $test1::var;
test2::step1();
print $test2::var;
评论:丑陋
{
package test1;
our $varref;
sub init {
my ($ref) = @_;
$varref = $ref;
}
sub step1 {$$varref = "Hello"}
}
{
package test2;
our $varref;
sub init {
my ($ref) = @_;
$varref = $ref;
}
sub step1 {$$varref .= " World!\n"}
}
my $var = "";
test1::init(\$var);
test2::init(\$var);
test1::step1();
test2::step1();
print $var;
评论:更好,但需要更多代码。
{
package test::shared;
our $var;
}
{
package test1;
sub step1 {$test::shared::var = "Hello"}
}
{
package test2;
sub step1 {$test::shared::var .= " World!\n"}
}
test1::step1();
test2::step2();
print $test::shared::var;
评论:有一些优势。
{
package test1;
sub step1 {
my $state = @_;
$state->{var} = "Hello";
return $state; # superfluous, but helps understanding
}
}
{
package test2;
sub step1 {
my $state = @_;
$state->{var} .= " World!\n";
return $state; # superfluous, but helps understanding
}
}
my $state = {};
$state = test1::step1($state); # equiv: test1::step1($state), because of references
$state = test2::step1($state);
print $state->{var};
评论:这几乎是面向对象的编程。我更喜欢这种模式,因为它明确指出何时共享。显式状态使得在多线程和重入性方面可以轻松扩展应用程序。
成本:明确性。详细的语法。
好处:通过明确性重新思考,清晰的思路。
答案 1 :(得分:1)
明显的免责声明,这是 BAD BAD BAD DESIGN ,您可以简单地使用globs:
==> exec.pl <==
#!/usr/bin/perl
use strict;
use warnings;
# You can omit this line, but there will be a warning about $My::Var being used only once
$My::Var = undef;
require 's1.pl';
require 's2.pl';
print $My::Var . "\n";
==> s1.pl <==
$My::Var = "Hello";
==> s2.pl <==
$My::Var .= "World";
Globs基本上是包裹状态的条目。包变量和子程序存在于包存储内;存储条目称为globs。
http://perldoc.perl.org/perlguts.html#Stashes-and-Globs
stashes和globs的相对简单以及操作它们的容易程度是我认为Perl非常酷的事情之一。
答案 2 :(得分:1)
主要问题是使用my
声明的变量不是包变量,并且无法通过使用包名称对其进行完全限定来访问它。但是,即使您使用our
声明了包变量,仍然有test1.pm
和execTests,pl
引用$test1::var
而test2.pm
正在使用$test2::var
}
我建议您使用主程序的局部变量,并将其传递给两个步骤进行修改
像这样(测试和工作)
<强> test1.pm 强>
use strict;
use warnings;
package test1;
use parent 'Exporter';
our @EXPORT = qw/step1/;
sub step1 {
$_[0] = "Hello";
}
1;
<强> test2.pm 强>
use strict;
use warnings;
package test2;
use parent 'Exporter';
our @EXPORT = qw/step2/;
sub step2 {
$_[0] .= " World!\n";
}
1;
<强> execTests.pl 强>
use strict;
use warnings;
use test1;
use test2;
my $var;
step1($var);
step2($var);
print $var;
<强>输出强>
Hello World!