Perl 与x27之间的相互作用;出口商';使用变量';,和';本地';

Perl 与x27之间的相互作用;出口商';使用变量';,和';本地';,perl,scope,Perl,Scope,我试图将这种行为归结为最简单的测试用例。考虑以下两个模块: 下午三点 下午五时 现在,下面脚本的输出- use strict; use warnings; use Foo; { local $Bar::BarVar = 'modified'; Foo::foo(); } Foo::foo(); 是“original”打印两次,我希望它被“modified”然后是“original”,因为我希望local声明在其整个范围内替换包变量$Bar::BarVar,包括对foo()的第一

我试图将这种行为归结为最简单的测试用例。考虑以下两个模块:

下午三点 下午五时 现在,下面脚本的输出-

use strict;
use warnings;

use Foo;

{
  local $Bar::BarVar = 'modified'; 
  Foo::foo();
}

Foo::foo();

是“original”打印两次,我希望它被“modified”然后是“original”,因为我希望
local
声明在其整个范围内替换包变量
$Bar::BarVar
,包括对
foo()
的第一次调用。怎么解释?如何在本地重写
$Bar::BarVar

您可能听我说过
my
our
创建变量(后者有别名),但
local
只是临时备份值

我撒谎了

local
会进行备份,但不会备份值。它备份关联标量的地址,创建新标量,并将名称与新标量关联。在这种情况下,
$Bar::BarVar
表示新标量,而
$Foo::BarVar
表示旧标量

$ perl -E'
   *x = \$y;  say \$x, " - ", \$y;
   local $y;  say \$x, " - ", \$y;
'
SCALAR(0x44d7c70) - SCALAR(0x44d7c70)
SCALAR(0x44d7c70) - SCALAR(0x44ba130)
如果只备份值,问题就会消失

use Sub::ScopeFinalizer qw( scope_finalizer );

{
   my $backup = $Bar::BarVar;
   my $guard = scope_finalizer { $Bar::BarVar = $backup };
   $Bar::BarVar = 'modified'; 
   Foo::foo();
}
可能存在更专门的工具。

请参阅:

此列表中还有一项要添加。不要导出变量名。仅仅因为Exporter允许您这样做,并不意味着您应该这样做

 @EXPORT_OK = qw($svar @avar %hvar); # DON'T!
导出变量不是一个好主意。它们可以在引擎盖下改变,在远距离引起可怕的影响,难以追踪和修复。相信我:他们不值得

为了提供设置/获取类范围设置的功能,最好将访问器作为子例程或类方法提供


这个规则有一个例外:如果你有常量变量(比如使用创建的变量),你可以导出它们,因为根据定义,它们不能在远处创建效果。

同意,但我正在处理一些遗留代码:)尝试
print\$Foo::BarVar,\$Bar::BarVar
本地
之前和之后。
use Sub::ScopeFinalizer qw( scope_finalizer );

{
   my $backup = $Bar::BarVar;
   my $guard = scope_finalizer { $Bar::BarVar = $backup };
   $Bar::BarVar = 'modified'; 
   Foo::foo();
}
 @EXPORT_OK = qw($svar @avar %hvar); # DON'T!