【问题标题】:Why do `perl Foo.pm` and `perl -I. -mFoo -e1` behave differently?为什么要使用`perl Foo.pm` 和`perl -I。 -mFoo -e1` 表现不同?
【发布时间】:2013-07-16 08:05:58
【问题描述】:

在 Foo.pm 中使用此代码:

use strict;
use warnings;
package Foo;

BEGIN {
  $Foo::AUTHORITY = 'cpan:ETHER';
}
1;

将文件作为模块加载不会出错:

$ perl -I. -mFoo -e1
$

然而,直接加载文件:

$ perl Foo.pm
Name "Foo::AUTHORITY" used only once: possible typo at Foo.pm line 6.

而且,perl -e'require "Foo.pm"' 也不会发出警告。

为什么会有这种差异?显然文件的解析方式不同, 但是如何以及为什么?

【问题讨论】:

  • 你不必指定-I.,当前目录总是包含在@INC中。
  • @TLP - 不在污点模式
  • @mob 好的,几乎总是。
  • 是的,但是对于污点模式,在这些情况下必须在命令行上指定 -T。

标签: perl module warnings require


【解决方案1】:

从技术角度还是从语言设计角度“为什么”?

从语言的角度来看,这是有道理的,因为模块中引用的变量很可能是模块公共 API 的一部分。例如,Data::Dumper 公开了一组改变其行为的包变量。 (可以说是糟糕的设计,但是哼哼。)这些变量可能只在模块中被引用一次,但可能会被程序的其他部分引用。

如果它只在主脚本中被引用一次,并且没有模块引用它,那么它更有可能是一个错误,所以我们在脚本中得到了这个警告,而不是在模块中。

从技术角度来看,此警告是由gv.c 生成的。就我个人而言,我无法确定触发它的确切条件。

【讨论】:

    【解决方案2】:

    肯定是例外,因为某些模块会这样做

    if ($Me::Setting) {
       ...
    } else {
       ...
    }
    

    我们并不总是有 ouruse vars(后者取决于导入符号的另一个例外)。


    使用warn(Perl 端)或Perl_warner(C 端)发出警告。有问题的行是this one

    【讨论】:

    • 我也有猜测,但我感兴趣的是具体的事实。谢谢! :)
    • @Ether,但是您接受了一个答案,该答案做出了与我所做的相同的有根据的猜测(公共 API),而没有提供我所做的任何佐证(声明机制不存在)?跨度>
    • 他链接到源,这证实这是故意行为(并显示“如何”)。
    • 你在说什么?他没有链接到消息来源,也没有确认这是故意的。他甚至没有说他是否认为缺乏警告是故意的。恰恰相反,他说他不能做正面或反面。他只是指出了包含发出警告的代码的文件的名称。这不代表任何意图!这只是表明存在发出警告的代码,我们已经知道了。
    • 请注意,它位于包含处理包变量的所有代码的文件中。还会在哪里?它根本不代表意图!
    猜你喜欢
    • 2012-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2020-03-15
    • 1970-01-01
    • 2010-10-22
    相关资源
    最近更新 更多