4

模块:./FOO/BAR/Foobar.pm

use strict;
use warnings;

package Foobar;
   our($VERSION , @ISA , @EXPORT , @EXPORT_OK , %EXPORT_TAGS , $FOO);
   BEGIN {
      require Exporter;
      @ISA       = qw(Exporter);
      @EXPORT_OK = qw(&foo);
   }

   sub foo {
      print "Loaded\n";
      $FOO = q{some val};
   }

1;

程序:./Caller.pl

#!/usr/bin/perl

   use strict;
   use warnings;

   use FOO::BAR::Foobar qw/foo/;

   Foobar::foo();  # works
   foo();          # errors out - can't find &main::foo

我会列出我尝试过的所有东西,但还有很多 - 正如你所看到的,我有比列出的更多的全局 Foobar 全局变量。我已经删除了 BEGIN 并按照 PerlMonks 上 [older] 帖子中的建议做了一些其他的事情。

我想我曾经在某处读过,如果包名称与模块名称相同,则默认情况下,Exporter 会以某种方式工作。我不知道将模块放在子目录中是否会改变这种行为(?)。但是,我很想看看我是怎么搞砸的。

4

2 回答 2

5

如果模块位于 FOO/BAR/Foobar.pm,那么包名应该是FOO::BAR::Foobar.

我还会&从 @EXPORT_OK 数组中删除符号。

于 2012-06-21T13:02:50.107 回答
4

除了 choroba 的回答,我还发现了Sherm Pendley的这篇文章,我认为这与我几年前读过的相同:

在导出函数的非 OO 模块中,它们必须相同,Exporter 才能执行其操作。当你使用()一个模块时——我们称之为“Foo”,以下步骤基本上是发生的:

BEGIN {
   require Foo;
   import Foo qw(args);
}

第二步是可选的 - 如果模块 Foo 中没有 import() 函数,use() 仍然会成功。

现在,让我们假设包 Bar 在 Foo.pm 中。Foo.pm 由 require() 编译,没有问题。因为它的代码在包 Bar 中,所以显式声明或从 Exporter 继承的 import() 函数也被编译到该包中。

但是 use() 仍然尝试调用 Foo 包中的 import() 函数。更糟糕的是,因为 import() 是可选的,它会默默地失败。用户将得到出错的唯一线索是,如果没有完全指定的包名称,即 Bar::baz(),包 Bar 中声明的任何函数都无法使用,因为 import() 未能创建当前包中它们的别名。

其他事情也可能取决于 filename = package 约定。以 perldoc 为例。如果您模块的用户运行“perldoc Foo”来获取您模块的文档,它将读取在 Foo.pm 中找到的文档。如果这些文档描述了一个名为“Bar”的包,用户会感到困惑。

即使您的模块是“纯”OO 并且不导出任何内容,遵循既定约定也有助于避免混淆 - 想象一个维护程序员在一年后查看您的脚本,并看到以下内容:

use Foo;
my $bar = Bar->new();

看到 Foo.pm 中定义的类 Bar 不是很直观。

所以不,理论上不需要。但是将它们命名为相同的约定被广泛遵循,实际上它或多或少是需要的。


因此,似乎每个模块有多个包,只有与文件同名的包才能导出其变量/函数。我怀疑如果你要为其他包创建自己的导入函数(?),你可以让它工作。

无论如何,在我的示例中,如果我不想将称为整个层次结构树,我可以设置 lib:

use lib './FOO/BAR';
use Foobar qw/foo/;   # instead of "use FOO::BAR::Foobar"

这意味着我仍然可以拥有Foobar.pm并在其中package Foobar而不是package FOO::BAR::Foobar

于 2012-06-21T13:45:57.870 回答