9

我想创建几个模块,这些模块将用于我项目中的几乎所有脚本和模块。这些可以在我的每个脚本中使用,如下所示:

#!/usr/bin/perl

use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;

# Potentially many more.

是否可以将所有这些使用语句移动到一个新模块Foo::Corge,然后只需要use Foo::Corge在我的每个脚本和模块中?

4

6 回答 6

7

像这样的东西应该工作:

http://mail.pm.org/pipermail/chicago-talk/2008-March/004829.html

基本上,创建包含大量模块的包:

package Lots::Of::Modules;
use strict; # strictly optional, really

# These are the modules we want everywhere we say "use Lots::Of::Modules".
# Any exports are re-imported to the module that says "use Lots::Of::Modules"
use Carp qw/confess cluck/;
use Path::Class qw/file dir/;
...

sub import {
    my $caller = caller;
    my $class  = shift;

    no strict;
    *{ $caller. '::'. $_ } = \*{ $class. '::'. $_ }
       for grep { !/(?:BEGIN|import)/ } keys %{ $class. '::' };
}

然后在别处使用Lots::Of::Modules;

use Lots::Of::Modules;
confess 'OH NOES';
于 2009-01-13T03:06:44.000 回答
7

是的,这是可能的,但不,你不应该这样做。

我只花了两个星期来摆脱一个除了使用其他模块什么都不做的模块。我猜这个模块一开始是简单而无辜的。但多年来,它成长为一个巨大的野兽,拥有大量的使用语句,其中大部分对于我们的 web 应用程序的任何给定运行都不需要。最后,仅仅“使用”那个模块就花了大约 20 秒。它支持惰性复制和粘贴模块创建。

再说一遍:你可能会在几个月或几年后后悔那一步。你有什么好处?您节省了在几个模块中输入几行代码。大不了。

于 2009-01-13T08:49:25.867 回答
3

是的。

在 Foo/Corge.pm

use Foo::Bar;
use Foo::Baz;
use Foo::Qux;
use Foo::Quux;

1;   # Be successful

剩下的就是将包含子目录的目录Foo添加到您的库路径 ( @INC) 中。或者,创建Foo.pm并让它使用其他模块。它们将Foo位于 旁边的子目录中Foo.pm

如果你仔细想想,所有使用其他模块的复杂 Perl 模块都会一直这样做。它们不一定在同一个顶级包中(Foo在这个例子中),但它们的使用是一样的。

虽然您可以使用 Carp 和 Path::Class 并承认,等等(正如 jrockway 所建议的那样),但从我坐的地方来看,这似乎有点矫枉过正。

于 2009-01-13T04:21:14.847 回答
0

[编辑:我之前涉及的解决方案use Lots::Of::Modules;有一个微妙的错误——见底部。该修复使事情变得有点丑陋,但仍然可行。]

[编辑#2:BEGIN { ... }在代码周围添加以确保定义的任何函数在编译时可用。感谢 jrockway 指出这一点。]

以下代码将完全按照 jrockway 的代码所做的,只是更简单和更清晰:

在很多/Of/Modules.inc 中:

use Carp qw/confess cluck/;
use Path::Class qw/file dir/;

0;   # Flag an error if called with "use" or "require" instead of "do"

要导入这 4 个函数:

BEGIN { defined( do 'Lots/Of/Modules.inc' ) or die; }

package Lots::Of::Modules;因为我们在这个文件的开头没有语句,所以这些use语句将导出到调用者的包中。

我们必须使用do代替useor require,因为后者只会加载文件一次(如果use Lots::Of::Modules;多次调用会导致失败,例如在use主程序的单独模块中)。do如果在 中找不到由其参数命名的文件,则更原始的不会引发异常@INC,因此需要使用defined.

于 2009-01-14T05:00:58.013 回答
0

另一种选择是让 Foo::Corge 正常重新导出任何感兴趣的项目:

package Foo::Corge;

use base 'Exporter';
BEGIN {
  our @EXPORT_OK = qw( bar baz qux quux );

  use Foo::Bar qw( bar );
  use Foo::Baz qw( baz );
  use Foo::Qux qw( qux );
  use Foo::Quux qw( quux );
}
1;

( ' use' 语句可能会出现BEGIN在其中可能不适用于您的情况。)evaluseBEGIN

于 2009-02-03T12:12:14.173 回答
0

使用 @EXPORT 而不是 @EXPORT_OK ,更简单

图书馆是:

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(test);

sub test {
    print "this is a test";
}

1;

用它:

#!/usr/bin/perl
use strict;
use warnings;
use mycommon;

common::test()
于 2013-11-14T21:44:31.737 回答