【问题标题】:Why does Perl not warn if using an undeclared variable in another namespace - and how can I be warned about this?如果在另一个命名空间中使用未声明的变量,为什么 Perl 不会发出警告 - 我如何得到警告?
【发布时间】:2017-02-27 14:40:00
【问题描述】:

我在我的 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 variables warnings


    【解决方案1】:

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

    strict vars

    如果您访问的变量既没有显式声明(使用 myourstateuse vars 中的任何一个)也没有完全限定,则会生成编译时错误。

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

    使用全局变量产生的问题的答案是不要使用全局变量。

    【讨论】:

    • Re "我认为没有办法检测到你指定了一个不存在的变量$BAR::foo",不,不是这样。如果 Perl 可以判断出该变量没有被使用,那么无论它在代码中如何命名,它都可以这样做。
    【解决方案2】:

    strict vars

    如果您访问的变量既没有显式声明(使用myourstateuse vars 中的任何一个)也没有完全限定,则会产生编译时错误。

    当用户使用完全限定的 var 名称时,Perl “信任”用户。我怀疑这是允许用户在不使用use strict;的模块中设置配置变量。

    例如,我们看下面的sn-p使用Data::Dumper:

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

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

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


    我想知道是否可以让 Perl 警告我在其他命名空间中使用未声明的变量。

    我不知道现有的解决方案。或许可以挂接到 Perl 中来做到这一点,但这会非常困难。

    请记住,如果您只使用一次包变量,Perl 已经警告您,因此这应该有助于您发现拼写错误。

    【讨论】:

      猜你喜欢
      • 2013-11-30
      • 1970-01-01
      • 2015-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多