为什么 Perl 在使用 bigint 时警告 "useless constant 1"?

Why does Perl warn about "useless constant 1" when using bigint?

我正在编写一个模块作为我的应用程序的一部分,这时我注意到语法检查的结果是关于 常量 (1) 无用使用的警告。这是为什么?

常量是模块末尾的强制性 1,通常会被警告忽略,如 perldoc perldiag 所说:

This warning will not be issued for numerical constants equal to 0 or 1 since they are often used in statements like

1 while sub_with_side_effects();

(可能有更好的来源。毕竟文件末尾的 1 是完全需要的,不需要警告。)

但是如果 use bigint.

即使模块几乎为空,也会生成警告
package Foo;

use bigint;

1;

对于这个简单的文件语法检查会产生以下警告:

$> perl -Wc Foo.pm
Useless use of a constant (1) in void context at Foo.pm line 5.
Foo.pm syntax OK

除了 Put long hex numbers in sqlite 之外,我找不到对 bigint 和警告消息的任何引用,但我认为这并没有真正解决我的问题。

我的 Perl 在 Cygwin 上是 v5.14.4,bigint 0.36。

-W 而不是模块中的 use warnings; 或使用 -c 而不是 perl -MFoo -e0 检查模块可能会显示虚假错误。这是后者的一个例子。

当您正常加载一个模块时,它不是在空上下文中,因为它正在检查结果是否为真。

(请注意,当我尝试使用 5.20.1 时,-W 也会导致虚假的 overload arg '..' is invalid at /usr/share/perl/5.20/Math/BigInt.pm line 155。)

这里有两个问题。

  1. 为什么 use bigint; 1; 在 void 上下文中发出警告?
  2. 为什么首先在 void 上下文中执行常量?

$ perl -c -we'1 while sub_with_side_effects();'
-e syntax OK

$ perl -c -we'use bigint; 1 while sub_with_side_effects();'
Useless use of a constant (1) in void context at -e line 1.
-e syntax OK

为什么 use bigint; 1; 在 void 上下文中发出警告?

use bigint; 安装一个回调,当解析器遇到常量文字时调用该回调,并且由回调编辑的值 return 用作常量。因此,在 use bigint; 下,1 不再只是简单的 01.

但是你没有做错任何事,所以这个警告是虚假的。您可以使用 ()undef 而不是 1.

来解决它
undef while sub_with_side_effects();

除非我需要在整个代码库中使用它,否则我会赞成以下内容:

while ( sub_with_side_effects() ) { }

$ cat Module.pm
package Module;
use bigint;
1;

$ perl -c -w Module.pm
Useless use of a constant (1) in void context at Module.pm line 3.
Module.pm syntax OK

为什么常量在空上下文中执行?

当 Perl 执行 模块 时,Perl 期望模块return 标量值,因此 Perl 应该在标量上下文中执行模块。

但是,您告诉 Perl 编译 脚本 Module.pm。当 Perl 执行脚本时,Perl 不需要 returned 任何值,因此 Perl 在空上下文中执行脚本。

将模块用作脚本会导致虚假警告和错误,传递 -W 也是如此。使用如下方法测试模块:

perl -we'use Module'

实际上,您甚至不需要 -w,因为模块中应该已经有 use warnings;。您真正需要的是

perl -e'use Module'

只是在这里留下一个避免警告的解决方法:在使用 bigint 之前定义一个值为 1 的常量:

package Foo;
use strict;
use warnings;
use constant PACKAGE_END => 1;
use bigint;

PACKAGE_END;