为什么不在Perl中使用严格和警告?

时间:2013-08-05 17:52:47

标签: perl

我已经看到混淆和高尔夫的代码保持关闭以避免声明变量,我可以看到在命令行上使用-e开关跳过它们以保持单行程更短。 在生产代码中您不希望use strict和/或use warnings的情况有哪些?您不希望使用它们的原因是什么?

问题出现了,因为我在这里看过有经验的Perl用户告诉Perl新手的人总是使用它们的帖子。

我确实在这里找到了一些相关问题,但他们没有解释我们可能希望关闭它们的情况。

3 个答案:

答案 0 :(得分:20)

strict pragma将您限制为Perl的理智子集。一些旧的功能具有历史意义(或者有单行的优点),但在现代可读的代码库中没有任何地方。

strict编译指示有三个类别:

  • "vars"强制您声明所有变量。这可以防止打字错误,并确保你选择一个范围(全局/词汇)。在单行中,这并不需要那么多,因为通常只有很少的范围和很少的变量。一些单行习语只能用于词法变量。

  • "refs"不允许使用symrefs。它们对词法变量毫无意义,Perl5有真正的参考。所以他们通常没用。但是,symrefs对于元编程仍然很有价值:

    # generate accessors
    for my $field (qw/foo bar baz/) {
      no strict 'refs';
      *{ __PACKAGE__ . '::' . $field } = sub { shift()->{$field} };
    }
    
  • "subs"强制将大多数裸字解释为子程序调用。这解决了foo . "bar"foo() . "bar"的歧义。如果未激活此类别,并且当前未定义foo sub,则它将被解析为"foo" . "bar"。这对于s​​hell程序员来说是有意义的,其中所有的裸字都是字符串。但是在Perl程序中,这会大大增加程序员的认知负担,并且不值得。

摘要:对于不进行优化以便于阅读的简单脚本,strict "vars"并非真正需要。在某些情况下需要no strict 'refs'

warnings编译指示允许对警告消息进行细粒度控制。这对于刚接触Perl的程序员来说尤为重要,因为Perl经常编写像

这样的东西
my %hash = { foo => 1, bar => 2 };

并想知道HASH(0x1234567)密钥来自哪里。即使在单线上,也需要警告,除非您使用undef等字符串化。

在专业代码库中,没有理由不在任何地方使用warnings 。如果脚本发出警告,则很可能存在错误,no warnings不会使此错误消失。您对Perl的了解从未像warnings pragma那样广泛。即使是大师也会犯错误。 use warnings是一个很棒的调试快捷方式。

也就是说,在部署程序时评论use warnings可能是好的。但永远不要发展。

根据开发团队的共识,也应该使用其他编译指示:

  • no indirect不允许厌恶的new Foo方法调用。我已经看到了可能在编译时被这个实用程序捕获的漏洞。
  • no autovivification阻止在$hash{doesnt_exist}{foo}之类的只读操作中出现引用。

答案 1 :(得分:9)

有时strictwarnings阻止您做您想做的事情,例如对符号表进行某些违反strict 'refs'的操作,或者重新定义{{1}的子例程会被触发。在其他时候,忽略某些警告比对其编写防御性代码更方便,例如对于可能包含warnings 'redefine'值的表的快速且脏的数据库转储将触发NULL/undef。 / p>

warnings 'uninitialized'use strict及其阻滞剂use warningsno strict可以是本地范围的,因此最佳做法是禁用no warnings和{{ 1}}在最小的实际范围内。

strict

答案 2 :(得分:4)

执行use strictuse warnings有助于某人了解Perl正在做什么。

有些人理解 Perl正在做什么以及为什么,所有的时间(即几乎没有人),有资格省略它们以节省空间和可能的执行时间。不幸的是,许多想要节省空间和时间的人是那些确切知道Perl正在做什么以及为什么做的人,他们对Perl正在做的事情的理解是基于如此多的错误假设从其他语言中学到的,绝对不允许他们忽略它们。

还有一些其他正当理由:

  • 尝试可能会产生警告的行为(例如,很多递归)
  • 使用旧的软件包(虽然我在2000年7月之后编写的任何软件包仍然没有生成use strictuse warnings的消息,所以这里的“旧”意味着真的很老,就像Perl版本一样4岁或以上)
  • 当你想利用没有人会想到的神奇的Perl行为(但是你因为你是专家而期望的那种行为)并且不想付出警告的代价这样做

顺便说一下,对于接受任何输入并根据该输入执行操作的程序,使用-T标志来帮助跟踪从用户输入获得的可能受污染的数据的使用也是非常重要的。

更新:@mob在一条带有一些调查的评论中提出索赔,即不使用严格和警告是微观优化,甚至低于平均微不足道的微观刺激。在下面的每种情况下,使用严格和警告的实际时间是12毫秒,并且在每种情况下,使用它们的实际时间是57毫秒或更长。

正如我原先所说的那样,在执行时间内有一个可能的好处(只有当你在模板中嵌入Perl脚本并在其中运行10或20个脚本时才会这样做每次加载网页的时间,例如),但仍然建议你使用它们,除非你真正确切知道Perl正在做什么以及为什么一直在做什么。 我对这类“专家”的描述旨在非常接近空集。如果您认为属于此类别,则自动不属于此类。

[j@5 ~]$ time perl -e '1;'

real    0m0.012s
user    0m0.005s
sys     0m0.007s
[j@5 ~]$ time perl -e '1;'

real    0m0.012s
user    0m0.010s
sys     0m0.005s
[j@5 ~]$ time perl -e '1;'

real    0m0.012s
user    0m0.011s
sys     0m0.001s
[j@5 ~]$ time perl -e '1;'

real    0m0.012s
user    0m0.004s
sys     0m0.007s
[j@5 ~]$ time perl -e '1;'

real    0m0.012s
user    0m0.005s
sys     0m0.007s
[j@5 ~]$ time perl -e 'use strict; use warnings;'

real    0m0.058s
user    0m0.058s
sys     0m0.000s
[j@5 ~]$ time perl -e 'use strict; use warnings;'

real    0m0.057s
user    0m0.041s
sys     0m0.016s
[j@5 ~]$ time perl -e 'use strict; use warnings;'

real    0m0.057s
user    0m0.033s
sys     0m0.025s
[j@5 ~]$ time perl -e 'use strict; use warnings;'

real    0m0.057s
user    0m0.050s
sys     0m0.009s