Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有没有一种方法可以;使用「;在Perl中使用多个其他文件的单个文件?_Perl_Module - Fatal编程技术网

有没有一种方法可以;使用「;在Perl中使用多个其他文件的单个文件?

有没有一种方法可以;使用「;在Perl中使用多个其他文件的单个文件?,perl,module,Perl,Module,我想创建几个模块,这些模块将用于我项目中几乎所有的脚本和模块中。在我的每一个脚本中都可以使用d,如下所示: #!/usr/bin/perl use Foo::Bar; use Foo::Baz; use Foo::Qux; use Foo::Quux; # Potentially many more. 是否可以将所有这些use语句移动到新模块Foo::Corge,然后只需在我的每个脚本和模块中使用Foo::Corge 基本上,创建包含大量模块的软件包: package Lots::Of:

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

#!/usr/bin/perl

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

# Potentially many more.

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

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

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';

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

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


虽然您可以使用Carp、Path::Class和坦白等等(正如jrockway所建议的那样),但从我现在的位置来看,这似乎有些过头了。

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

我刚刚花了两周的时间摆脱了一个只使用其他模块的模块。我猜这个模块一开始是简单和无辜的。但多年来,它成长为一个巨大的野兽,有着许许多多的使用声明,其中大部分都是我们的网络应用程序运行所不需要的。最后,仅仅“使用”这个模块就花了大约20秒。它支持延迟复制和粘贴模块创建


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

[编辑:我以前的解决方案涉及
使用Lots::Of::Modules;
有一个微妙的缺陷——请参见下文。该修复方案使事情变得更丑陋,但仍然可行。]

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

以下代码与jrockway的代码完全相同,只是更简单、更清晰:

在Lots/Of/Modules.inc中: 要导入这4个功能:

BEGIN { defined( do 'Lots/Of/Modules.inc' ) or die; }
因为我们没有
包Lots::Of::Modules
语句在该文件的开头,
use
语句将导出到调用者的包中


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

另一个选项是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
,但这就是我检查的代码中的语句,以验证它是否按我认为的方式工作。该代码实际上
eval
s
use
s,因此它们有理由位于
BEGIN
中,这可能不适用于您的情况。)使用@EXPORT代替@EXPORT\u 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()

我的示例假设您需要从每个模块导出符号。Class和Carp是导出符号的模块示例。当您“使用”Lots::Of::Modules时,您将得到定义Lots::Of::Modules时所使用的所有内容的导出。如果组合在一起的模块没有任何共同之处,我完全同意,但将具有内聚性的相关模块组合在一起实际上是一件好事,同样,将许多内聚的代码行组合到一个函数中,然后多次调用它也是很好的。我完全不同意。很抱歉如果所有模块都做了基本相同的事情,只是略有变化,会怎么样?为什么要一直使用它们,而不仅仅是你现在需要的?对于分组属于一起的东西,我们有Perl中的包名称空间。如果所有模块都做了基本相同的事情,当然,只使用一个而不是所有模块是有意义的。但是,如果您处理的是一组互补模块,为什么不将它们分组呢?我能看到的唯一缺点是,如果你让团队变得庞大,可能会出现性能问题。我不同意。很多其他语言都是这样做的——参见CL中的ASDF。使用模块的唯一方法是在任何地方使用它。使用模块的唯一方法是在任何地方使用它?-很抱歉,但我不知道这意味着什么。如果您依赖于编译时可用的函数,那么这不起作用,因为do在运行时运行。副作用是导入函数上的原型无法工作。jrockway的观点很好。我添加了一个BEGIN块来纠正这个问题。它也有缺陷,因为它依赖于硬编码路径,而不是像“use”那样搜索@INC。对于本地开发来说没什么大不了的,但是当你尝试在其他地方安装它时,一定要玩得开心…@Dave Sherohman:我同意这是个问题。主要的问题是“使用”几乎正是我们想要的——如果有某种方法迫使它总是包含文件,那么这种丑陋的解决方法是可以避免的。(可能是“BEGIN{local%INC;use Lots::Of::Modules;}”)use=require+import。需要运行一次,导入每次运行。这将无法导出包含单词“BEGIN”或“import”(例如名为“do_important_work()”)的函数--请将正则表达式更改为/\a(?:BEGIN | import)\z/以解决此问题。它还需要一个真正的表达式(例如“1;”)作为最后一个语句。更多子语句
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()