perl包是否自动生效?它们究竟是如何工作的?

时间:2015-12-29 06:43:17

标签: perl

我试图弄清楚是否可以动态创建一个Perl包,所以我写了一个简单的测试程序。

eval "package foobar;";

$foobar::baz = 4;
print $foobar::baz;

该程序打印4。然后我试了

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

eval "package foobar;";

$foobar::baz = 4;
print $foobar::baz;

程序没有崩溃并且没有被拒绝(并且仍然打印4),尽管事实上直到运行时才知道foobar包存在。

然后我试了

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

$foobar::baz = 4;
print $foobar::baz;

并且Perl仍然乐意打印4

我现在彻底困惑了。我一直认为必须明确创建包,而不仅仅是应运而生。它们究竟是如何工作的?是否存在可以在“使用”包而未通过package“声明”包时发出警告的编译指示?

3 个答案:

答案 0 :(得分:4)

从某种意义上说,包只不过是哈希中的键,恰好是符号表。在示例代码中设置%foobar::后,可以通过检查哈希$foobar::baz来查看此内容。之后,您可以开始查看%::。通过直接弄乱符号表,可以做一些有趣的事情(以及难以理解和棘手的调试)。

要阅读所有这些内容的文档页面是perlmod

答案 1 :(得分:3)

  

perl软件包是否已自动生效?

  

它们究竟是如何运作的?

package确实可用于创建包。

$ perl -E'
    BEGIN { say $main::{"Foo::"} ? "exists" : "doesn'\''t exist"; }
    { package Foo; }
    BEGIN { say $main::{"Foo::"} ? "exists" : "doesn'\''t exist"; }
'
doesn't exist
exists

但它的主要目的是指定非限定包变量的位置。

正如您所发现的那样,只要包中引用了某个符号,就会在必要时自动创建该包(以及任何父包)。

$ perl -E'
    BEGIN { say $main::{"Foo::"} ? "exists" : "doesn'\''t exist"; }
    $Foo::bar;
    BEGIN { say $main::{"Foo::"} ? "exists" : "doesn'\''t exist"; }
'
doesn't exist
exists
在编译时引用了

$Foo::bar,这就是为什么在编译行BEGIN之前使用$Foo::bar来运行代码的原因。

  

是否存在可以在使用包裹时发出警告的编译指示'没有被宣布'通过包?

我很确定没有。我非常确定Perl本身需要代码(而不是可以从CPAN下载的扩展)。

然而,你可能会遇到只使用过一次的"警告。

$ perl -we'use Data::Dumper; $Data::Lumper::Useqq = 1; print(Dumper("\n"));'
Name "Data::Lumper::Useqq" used only once: possible typo at -e line 1.
$VAR1 = '
';

$ perl -we'use Data::Dumper; $Data::Dumper::Useqq = 1; print(Dumper("\n"));'
$VAR1 = "\n";

当然,如果您避免使用完全限定名称(通过提供更好的界面),则可以完全避免此问题。

答案 2 :(得分:2)

我不会将其称为 autovivified ,因为它通常是指在引用时创建匿名数组和哈希值。但是没有必要声明包,并且所有package都会定义默认包,如果它们不是完全限定的,那么将存储所有后续子例程和our变量