如果在另一个名称空间中使用未声明的变量,为什么 Perl 不发出警告 - 我如何收到警告?

Why does Perl not warn if using an undeclared variable in another namespace - and how can I be warned about this?

我在我的 Perl 脚本中使用 strictwarning,以便在我使用未声明的变量时收到通知。因此,解释器将警告 $foo 在以下脚本中未声明:

#!/usr/bin/perl
use warnings;
use strict;

$foo = 'bar';
print ($foo);

但是,如果我在另一个命名空间中使用未声明的变量,则不会收到警告。以下 scriptlet 在没有任何警告的情况下运行。

#!/usr/bin/perl
use warnings;
use strict;

$BAR::foo = 'bar';
print ($BAR::foo);

为什么会有这种差异?

由于我花了很多时间来弄清楚这个问题,尽管是在更大的上下文中,我想知道是否有可能让 Perl 我也警告在其他名称空间中使用未声明的变量。

当您完全指定变量所属的名称空间时,perl 假定您知道自己在做什么。见 perldoc strict:

strict vars

This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.

我认为没有办法检测到您指定了一个不存在的变量 $BAR::foo。但是,如果 BAR 包在你的控制之下,你可以首先避免使用包变量,方法是使用访问器调解对 foo 状态的访问,并对其他模块隐藏该变量。

解决使用全局变量产生的问题的方法是不使用全局变量。

strict vars

This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.

Perl 在用户使用完全限定的 var 名称时“信任”他们。我怀疑这是为了允许用户在不使用 use strict;.

的模块中设置配置变量

例如,让我们看看下面使用 Data::Dumper 的片段:

local $Data::Dumper::Useqq = 1;
print(Dumper($s));

即使在引入 use strict; 很久之后,Data::Dumper 也没有声明 $Useqq。在 use strict; 之前甚至都没有这样做的机制!所以上面的代码片段将使用一个未声明的变量。这意味着如果 strict vars 被强制覆盖完全限定名称,则严格代码将无法以上述方式使用 Data::Dumper。

阻止严格代码使用非严格安全的模块没有意义,因此 strict vars 不涵盖完全限定名称。这些非常罕见且易于识别,足以让程序员在使用它们时更加小心。


I am wondering if it is possible to make Perl me warn about using undeclared variables in other namespaces, too.

我不知道现有的解决方案。或许可以挂接到 Perl 来执行此操作,但这会非常困难。

请记住,如果您只使用一次包变量,Perl 已经警告您,所以这应该可以帮助您发现拼写错误。