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

hma*_*tt1 13 perl

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

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

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

amo*_*mon 20

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

strictpragma有三个类别:

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

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

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

简介:对于没有针对可读性进行优化的简单脚本,strict "vars"并不是必需的.有几种情况no strict 'refs'需要.

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

my %hash = { foo => 1, bar => 2 };
Run Code Online (Sandbox Code Playgroud)

并想知道那把HASH(0x1234567)钥匙来自哪里.即使是单线,也需要警告,除非您使用字符串undef等.

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

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

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

  • no indirect不允许厌恶的new Foo方法调用.我已经看到了可能在编译时被这个编译指示捕获的漏洞.
  • no autovivification防止在只读操作上弹出的引用$hash{doesnt_exist}{foo}.


mob*_*mob 9

有时strictwarnings阻止你做你想要做的事情,就像这将违反符号表做某些操作strict 'refs',或重新定义一个子程序,其中warnings 'redefine'将被触发.在其他时候,忽略某些警告比对其编写防御性代码更方便,例如对于可能包含NULL/undef将触发的值的表的快速脏数据库转储warnings 'uninitialized'.

use strict并且use warnings,它们的阻燃剂no strictno warnings可局部范围,所以它是禁用的最佳实践strict,并warnings在实践最小范围.

@data = get_some_data_from_database();
if (some_condition()) {
    no warnings 'uninitialized';
    logger->debug("database contains: @$_") for @data;

    ## otherwise, suppressing the warnings would take something
    ## less readable and more error-prone like:
    #  logger->debug("database contains: @{[map{defined?$_:''}@$_]}") for @data
    #  logger->debug("database contains: @{[map{$_//''}@$_]}") for @data
}
# end of scope, warnings `uninitialized' is enabled again
Run Code Online (Sandbox Code Playgroud)

  • 我不是在投票,但是在你的回答中给出这样一个代码示例的唯一困扰是人们会放大这些代码.当同事问我这个问题时,我常常给出同样的答案(代码示例).而我从经验中发现的是,这种代码示例使得很多"脚本小子"在代码的各个部分都没有任何理由关闭警告,只是因为他们认为它使它们看起来像"专家". (2认同)