perl - 'Exporter'、 'use vars' 和 'local' 之间的交互

标签 perl scope

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

酒吧.pm

package Bar;

use base 'Exporter';
use vars qw/ $BarVar /;
BEGIN { @EXPORT_OK = qw/ $BarVar /; }

$BarVar = 'original';

1;

Foo.pm

package Foo;

use Bar qw/ $BarVar /;

sub foo { print $BarVar . "\n"}

1;

现在,以下脚本的输出 -

use strict;
use warnings;

use Foo;

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

Foo::foo();

是“original”打印了两次,我希望它被“modified”后跟“original”,因为我希望用 local 声明来替换包变量 $Bar::BarVar 贯穿其整个范围,其中包括对 foo() 的第一次调用。有何解释?如何在本地覆盖 $Bar::BarVar

最佳答案

您可能听过我说过 myour 创建变量(后者是别名),但是 local 只是使该值的临时备份。

我撒谎了。

local 确实进行了备份,但没有备份值(value)。它备份关联标量的地址,创建一个新标量,并将名称与新标量关联起来。在这种情况下,$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();
}

可能存在更专业的工具。

关于perl - 'Exporter'、 'use vars' 和 'local' 之间的交互,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31864081/

相关文章:

javascript - 将 this 保存在类的实例对象中

perl - 处理相互使用的模块的最佳方式是什么?

perl - 寻找适用于 Windows 10 的小型 Perl 实现

javascript - JavaScript 模块模式中的方括号符号和作用域

javascript - 将函数插入数组,将 let 转换为 var

javascript - 使用字符串作为函数调用范围

PowerShell 在多个提示函数和作用域之间切换

perl - 如何在 Perl 中的匹配行之后抓取多行?

regex - 何时使用相等运算符而不是绑定(bind)运算符

regex - 为 CGI 输入域名的 Perl 污染模式导致 “Insecure dependency in eval”