我试图弄清楚是否可以动态创建一个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
“声明”包时发出警告的编译指示?
答案 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
变量