Perl:导出器出了问题

时间:2012-06-21 12:39:34

标签: perl exporter

模块: ./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上[较旧]帖子的建议完成了其他一些事情。

我想我曾经读过一次,如果包名与模块名相同,则Exporter默认以某种方式工作。我不知道将模块放在子目录中是否可以改变该行为(?)。但是,我很想知道我是如何搞砸的。

2 个答案:

答案 0 :(得分:5)

如果模块位于FOO / BAR / Foobar.pm,则包名称应为FOO::BAR::Foobar

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

答案 1 :(得分:4)

除了choroba的回答,我在post找到了这个Sherm Pendley,我认为这是我多年前读过的那篇文章:

  

在导出函数的非OO模块中,它们必须相同   出口商要做的事情。使用()模块时 - 让我们称之为“Foo”,   以下步骤基本上是发生的事情:

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

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

     

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

     

但是use()仍尝试在包中调用import()函数   富。更糟糕的是,因为import()是可选的,它将静默失败。该   只有线索,用户会得到一个出错的地方,就是没有   包Bar中声明的函数可以在没有完全使用的情况下使用   指定的包名,即Bar :: baz(),因为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