【问题标题】:Perl: Trouble with ExporterPerl:导出器的问题
【发布时间】:2012-06-21 12:39:33
【问题描述】:

模块:./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 会以某种方式工作。我不知道将模块放在子目录中是否会改变这种行为(?)。不过,我很想看看我是怎么搞砸的。

【问题讨论】:

    标签: perl exporter


    【解决方案1】:

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

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

    【讨论】:

    • +1 --- 看来我的怀疑是有道理的。除了重命名包还有其他方法吗?
    • 我回答了上面的问题(在评论中)。我会接受这个作为答案 - 不过,我仍然想找到一些关于导入不同包的变量/函数的资源
    【解决方案2】:

    除了 choroba 的回答之外,我还发现了 postSherm 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 不是很直观。

    所以不,理论上不需要。但是命名它们的约定 同样被如此广泛地遵循,以至于在实践中它真的更多或 较少需要。


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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 1970-01-01
      • 2019-05-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多