简体   繁体   English

为什么使用严格和警告?

[英]Why use strict and warnings?

It seems to me that many of the questions in the Perl tag could be solved if people would use:在我看来,如果人们使用以下方法,Perl 标签中的许多问题都可以解决:

use strict;
use warnings;

I think some people consider these to be akin to training wheels, or unnecessary complications, which is clearly not true, since even very skilled Perl programmers use them.我认为有些人认为这些类似于训练轮或不必要的复杂性,这显然不是真的,因为即使是非常熟练的 Perl 程序员也会使用它们。

It seems as though most people who are proficient in Perl always use these two pragmas, whereas those who would benefit most from using them seldom do.似乎大多数精通 Perl 的人总是使用这两个 pragma,而那些从使用它们中获益最多的人很少这样做。 So, I thought it would be a good idea to have a question to link to when encouraging people to use strict and warnings .所以,我认为在鼓励人们use strictwarnings时有一个问题链接是个好主意。

So, why should a Perl developer use strict and warnings ?那么,为什么 Perl 开发人员应该use strictwarnings呢?

For starters, use strict;首先, use strict; (and to a lesser extent, use warnings; ) helps find typos in variable names. (并在较小程度上use warnings; )有助于查找变量名称中的拼写错误。 Even experienced programmers make such errors.即使是有经验的程序员也会犯这样的错误。 A common case is forgetting to rename an instance of a variable when cleaning up or refactoring code.一个常见的情况是在清理或重构代码时忘记重命名变量的实例。

Using use strict; use warnings;使用use strict; use warnings; use strict; use warnings; catches many errors sooner than they would be caught otherwise, which makes it easier to find the root causes of the errors.比其他方式更早地捕获许多错误,从而更容易找到错误的根本原因。 The root cause might be the need for an error or validation check, and that can happen regardless or programmer skill.根本原因可能是需要进行错误或验证检查,无论程序员技能如何,都可能发生这种情况。

What's good about Perl warnings is that they are rarely spurious, so there's next to no cost to using them. Perl 警告的好处在于它们很少是虚假的,因此使用它们几乎没有成本。


Related reading: Why use my ?相关阅读:为什么使用my

Apparently use strict should (must) be used when you want to force Perl to code properly which could be forcing declarations, being explicit on strings and subs, ie, barewords or using refs with caution.显然,当您想强制 Perl 正确编码时,应该(必须) use strict ,这可能会强制声明,在字符串和子项上显式,即裸字或谨慎使用 refs。 Note: if there are errors, use strict will abort the execution if used.注意:如果有错误, use strict会中止执行。

While use warnings; use warnings; will help you find typing mistakes in program like you missed a semicolon, you used 'elseif' and not 'elsif', you are using deprecated syntax or function, whatever like that.将帮助您找到程序中的输入错误,例如您错过了分号,您使用了“elseif”而不是“elsif”,您使用的是不推荐使用的语法或函数,诸如此类。 Note: use warnings will only provide warnings and continue execution, ie, it won't abort the execution...注意:使用警告只会提供警告并继续执行,即不会中止执行...

Anyway, it would be better if we go into details, which I am specifying below无论如何,如果我们详细说明会更好,我在下面指定

From perl.com (my favourite):来自perl.com (我最喜欢的):

use strict 'vars';使用严格的“变量”;

which means that you must always declare variables before you use them.这意味着您必须始终在使用变量之前声明它们。

If you don't declare you will probably get an error message for the undeclared variable:如果您不声明,您可能会收到未声明变量的错误消息:

Global symbol "$variablename" requires explicit package name at scriptname.pl line 3全局符号“$variablename”需要在 scriptname.pl 第 3 行显式包名

This warning means Perl is not exactly clear about what the scope of the variable is.这个警告意味着 Perl 并不清楚变量的作用域是什么。 So you need to be explicit about your variables, which means either declaring them with my , so they are restricted to the current block, or referring to them with their fully qualified name (for ex: $MAIN::variablename).所以你需要明确你的变量,这意味着要么用my声明它们,所以它们仅限于当前块,要么用它们的完全限定名称(例如:$MAIN::variablename)引用它们。

So, a compile-time error is triggered if you attempt to access a variable that hasn't met at least one of the following criteria:因此,如果您尝试访问至少不满足以下条件之一的变量,则会触发编译时错误:

  • Predefined by Perl itself, such as @ARGV , %ENV , and all the global punctuation variables such as $ .由 Perl 本身预定义,例如@ARGV%ENV ,以及所有全局标点变量,例如$ Or $_ .$_

  • Declared with our (for a global) or my (for a lexical).用 our(对于全局)或 my(对于词法)声明。

  • Imported from another package.从另一个包导入。 (The use vars pragma fakes up an import, but use our instead.) use vars pragma 伪造了一个导入,但使用our代替。)

  • Fully qualified using its package name and the double-colon package separator.使用其包名和双冒号包分隔符进行完全限定。

use strict 'subs';使用严格的“subs”;

Consider two programs考虑两个程序

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

In both cases we have a test_value() sub and we want to put its result into $a.在这两种情况下,我们都有一个 test_value() sub 并且我们想将它的结果放入 $a 中。 And yet, when we run the two programs, we get two different results:然而,当我们运行这两个程序时,我们得到了两个不同的结果:

In the first program, at the point we get to $a = test_value;在第一个程序中,我们得到$a = test_value; , Perl doesn't know of any test_value() sub, and test_value is interpreted as string 'test_value'. , Perl 不知道任何 test_value() 子,并且 test_value 被解释为字符串 'test_value'。 In the second program, the definition of test_value() comes before the $a = test_value;在第二个程序中,test_value() 的定义出现在$a = test_value;之前$a = test_value; line.线。 Perl thinks test_value as sub call. Perl 认为 test_value 是子调用。

The technical term for isolated words like test_value that might be subs and might be strings depending on context, by the way, is bareword .对于隔离的话犹如test_value这可能是潜艇,并且可能依赖于上下文字符串的技术术语,顺便说一句,是裸字 Perl's handling of barewords can be confusing, and it can cause bug in program. Perl 对裸字的处理可能会令人困惑,并且可能导致程序中的错误。

The bug is what we encountered in our first program, Remember that Perl won't look forward to find test_value() , so since it hasn't already seen test_value(), it assumes that you want a string.这个 bug 就是我们在第一个程序中遇到的,记住 Perl 不会期待找到test_value() ,所以因为它还没有看到 test_value(),它假设你想要一个字符串。 So if you use strict subs;所以如果你use strict subs; , it will cause this program to die with an error: ,它会导致这个程序因错误而死亡:

Bareword "test_value" not allowed while "strict subs" in use at ./a6-strictsubs.pl line 3.在 ./a6-strictsubs.pl 第 3 行使用“strict subs”时不允许使用裸词“test_value”。

Solution to this error would be此错误的解决方案是

  1. Use parentheses to make it clear you're calling a sub.使用括号明确表示您正在调用 sub。 If Perl sees $a = test_value();,如果 Perl 看到 $a = test_value();,

  2. Declare your sub before you first use it在你第一次使用它之前声明你的子

    use strict;使用严格; sub test_value;子测试值; # Declares that there's a test_value() coming later ... my $a = test_value; # 声明稍后会有一个 test_value() ... my $a = test_value; # ...so Perl will know this line is okay. # ...这样 Perl 就会知道这行代码没问题。 ....... sub test_value { return "test_passed"; ....... sub test_value { return "test_passed"; } }

  3. And If you mean to use it as a string, quote it.如果您打算将其用作字符串,请引用它。

So, This stricture makes Perl treat all barewords as syntax errors.因此,这种限制使 Perl 将所有裸词都视为语法错误。 A bareword is any bare name or identifier that has no other interpretation forced by context.一个裸是任何裸名称或标识符,没有上下文强制的其他解释。 (Context is often forced by a nearby keyword or token, or by predeclaration of the word in question.) So If you mean to use it as a string, quote it and If you mean to use it as a function call, predeclare it or use parentheses. (上下文通常由附近的关键字或标记或相关单词的预先声明强制。)因此,如果您打算将其用作字符串,请引用它;如果您打算将其用作函数调用,请预先声明它或使用括号。

Barewords are dangerous because of this unpredictable behavior.由于这种不可预测的行为,裸词很危险。 use strict; (or use strict 'subs';) use strict; (or use strict 'subs';) makes them predictable, because barewords that might cause strange behavior in the future will make your program die before they can wreak havoc use strict; (or use strict 'subs';)使它们可预测,因为将来可能导致奇怪行为的裸词将使您的程序在它们造成严重破坏之前死亡

There's one place where it's OK to use barewords even when you've turned on strict subs: when you are assigning hash keys.有一个地方可以使用裸词,即使您打开了严格的 subs:当您分配哈希键时。

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Barewords in hash keys are always interpreted as strings, so there is no ambiguity.哈希键中的裸词总是被解释为字符串,所以没有歧义。

use strict 'refs';使用严格的“参考”;

This generates a run-time error if you use symbolic references, intentionally or otherwise.如果您有意或无意地使用符号引用,则会产生运行时错误。

A value that is not a hard reference is then treated as a symbolic reference .不是硬引用的值然后被视为符号引用 That is, the reference is interpreted as a string representing the name of a global variable.也就是说,引用被解释为表示全局变量名称的字符串。

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

use warnings;使用警告;

This lexically scoped pragma permits flexible control over Perl's built-in warnings, both those emitted by the compiler as well as those from the run-time system.这个词法范围的 pragma 允许灵活控制 Perl 的内置警告,包括编译器发出的警告和运行时系统发出的警告。

From perldiag :perldiag

So the majority of warning messages from the classifications below, ie, W, D, and S can be controlled using the warnings pragma.因此,可以使用warnings编译指示控制来自以下分类(即 W、D 和 S)的大多数警告消息。

(W) A warning (optional) (W) 警告(可选)
(D) A deprecation (enabled by default) (D) 弃用(默认启用)
(S) A severe warning (enabled by default) (S) 严重警告(默认启用)

I have listed some of warnings messages those occurs often below by classifications.我已经按分类列出了一些经常出现在下面的警告消息。 For detailed info on them and others messages, refer to perldiag .有关它们和其他消息的详细信息,请参阅perldiag

(W) A warning (optional): (W) 警告(可选):

Missing argument in %s %s 中缺少参数
Missing argument to -%c缺少 -%c 的参数
(Did you mean &%s instead?) (你是说 &%s 吗?)
(Did you mean "local" instead of "our"?) (你的意思是“本地”而不是“我们的”?)
(Did you mean $ or @ instead of %?) (你的意思是 $ 或 @ 而不是 %?)
'%s' is not a code reference “%s”不是代码引用
length() used on %s %s 上使用的 length()
Misplaced _ in number数字错位 _

(D) A deprecation (enabled by default): (D) 弃用(默认启用):

defined(@array) is deprecated已定义(@array)已弃用
defined(%hash) is deprecated已定义(%hash)已弃用
Deprecated use of my() in false conditional不推荐在 false 条件中使用 my()
$# is no longer supported不再支持 $#

(S) A severe warning (enabled by default) (S) 严重警告(默认启用)

elseif should be elsif elseif 应该是 elsif
%s found where operator expected %s 找到操作员预期的位置
(Missing operator before %s?) (在 %s 之前缺少运算符?)
(Missing semicolon on previous line?) (前一行缺少分号?)
%s never introduced %s 从未介绍过
Operator or semicolon missing before %s %s 之前缺少运算符或分号
Precedence problem: open %s should be open(%s)优先级问题:open %s 应该是 open(%s)
Prototype mismatch: %s vs %s原型不匹配:%s 与 %s
Warning: Use of "%s" without parentheses is ambiguous警告:不带括号的“%s”的使用不明确
Can't open %s: %s无法打开 %s: %s

These two pragmas can automatically identify bugs in your code.这两个 pragma 可以自动识别代码中的错误。

I always use this in my code:我总是在我的代码中使用它:

use strict;
use warnings FATAL => 'all';

FATAL makes the code die on warnings, just like strict does. FATAL使代码在警告时死亡,就像strict一样。

For additional information, see: Get stricter with use warnings FATAL => 'all';有关其他信息,请参阅:使用警告更严格 FATAL => 'all';

Also... The strictures, according to Seuss也......根据苏斯的说法,这些限制

There's a good thread on perlmonks about this question.关于这个问题的perlmonks一个很好的线程

The basic reason obviously is that strict and warnings massively help you catch mistakes and aid debugging.根本原因显然是严格和警告可以大量帮助您发现错误并帮助调试。

Source: Different blogs来源:不同的博客

Use will export functions and variable names to the main namespace by calling modules import() function. Use 将通过调用模块 import() 函数将函数和变量名称导出到主命名空间。

A pragma is a module which influences some aspect of the compile time or run time behavior of Perl. pragma 是一个模块,它影响 Perl 的编译时或运行时行为的某些方面。 Pragmas give hints to the compiler. Pragma 为编译器提供提示。

Use warnings - Perl complains about variables used only once and improper conversions of strings into numbers.使用警告 - Perl 会抱怨变量只使用一次以及将字符串不正确地转换为数字。 Trying to write to files that are not opened.尝试写入未打开的文件。 It happens at compile time.它发生在编译时。 It is used to control warnings.它用于控制警告。

Use strict - declare variables scope.使用严格 - 声明变量范围。 It is used to set some kind of discipline in the script.它用于在脚本中设置某种规则。 If barewords are used in the code they are interpreted.如果在代码中使用了裸字,它们将被解释。 All the variables should be given scope, like my, our or local.所有变量都应该有作用域,比如 my、our 或 local。

The "use strict" directive tells Perl to do extra checking during the compilation of your code. “use strict”指令告诉 Perl 在你的代码编译期间做额外的检查。 Using this directive will save you time debugging your Perl code because it finds common coding bugs that you might overlook otherwise.使用此指令将节省您调试 Perl 代码的时间,因为它会发现您可能会忽略的常见编码错误。

Strict and warnings make sure your variables are not global.严格和警告确保您的变量不是全局变量。

It is much neater to be able to have variables unique for individual methods rather than having to keep track of each and every variable name.能够为各个方法拥有唯一的变量而不是必须跟踪每个变量名称要简洁得多。

$_, or no variable for certain functions, can also be useful to write more compact code quicker. $_ 或某些函数没有变量,也可用于更快地编写更紧凑的代码。

However, if you do not use strict and warnings, $_ becomes global!但是,如果您不使用严格和警告,则 $_ 将变为全局!

use strict;
use warnings;

Strict and warnings are the mode for the Perl program.严格和警告是 Perl 程序的模式。 It is allowing the user to enter the code more liberally and more than that, that Perl code will become to look formal and its coding standard will be effective.它允许用户更自由地输入代码,不仅如此,Perl 代码将变得正式,其编码标准将有效。

warnings means same like -w in the Perl shebang line, so it will provide you the warnings generated by the Perl program.警告与 Perl shebang行中的-w含义相同,因此它将为您提供由 Perl 程序生成的警告。 It will display in the terminal.它将显示在终端中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM