如何导出Perl包中的所有subs?

时间:2009-04-08 22:25:59

标签: perl function export subroutine

我想将所有sub公开到我的命名空间中,而不必一次列出一个:

@EXPORT = qw( firstsub secondsub third sub etc );

使用完全限定名称需要对现有代码进行大量更改,因此我宁愿不这样做。

是否有@EXPORT_ALL?

我认为文档说这是一个坏主意,但无论如何我还是想这样做,或者至少知道如何。

回答Jon的原因:现在为了快速重构,我想将一堆sub转移到他们自己的包中,对现有脚本进行最少的麻烦和代码更改(这些子当前使用并经常重复)。

另外,大多数情况下,我只是好奇。 (因为看起来出口商似乎也可以将其作为标准功能,但到目前为止它基于答案有点令人惊讶,但它没有)

9 个答案:

答案 0 :(得分:23)

根本不要进行任何导出,也不要在库中声明包名。只需使用require加载文件,一切都将在当前包中。容易腻。

答案 1 :(得分:10)

别。但是如果你真的想...编写一个自定义import,它会遍历符号表并导出所有已命名的子程序。

# Export all subs in package. Not for use in production code!
sub import {
    no strict 'refs';

    my $caller = caller;

    while (my ($name, $symbol) = each %{__PACKAGE__ . '::'}) {
        next if      $name eq 'BEGIN';   # don't export BEGIN blocks
        next if      $name eq 'import';  # don't export this sub
        next unless *{$symbol}{CODE};    # export subs only

        my $imported = $caller . '::' . $name;
        *{ $imported } = \*{ $symbol };
    }
}

答案 2 :(得分:3)

警告,以下代码与导出所有内容一样糟糕:

package Expo;

use base "Exporter";

seek DATA, 0, 0; #move DATA back to package

#read this file looking for sub names
our @EXPORT = map { /^sub\s+([^({\s]+)/ ? $1 : () } <DATA>;

my $sub = sub {}; #make sure anon funcs aren't grabbed

sub foo($) {
    print shift, "\n";
}

sub bar ($) {
    print shift, "\n";
}

sub baz{
    print shift,"\n";
}

sub quux {
    print shift,"\n";
}

1;

__DATA__

以下是使用该模块的一些代码:

#!/usr/bin/perl

use strict;
use warnings;

use Expo;

print map { "[$_]\n" } @Expo::EXPORT;

foo("foo");
bar("bar");
baz("baz");
quux("quux");

这是它的输出:

[foo]
[bar]
[baz]
[quux]
foo
bar
baz
quux

答案 3 :(得分:2)

您始终可以使用完全指定的格式调用子例程:

MyModule::firstsub();

对于我在内部编写的模块,我发现这个约定非常有效。这是更多的打字,但往往是更好的文档。

请查看perldoc perlmod,了解有关您要完成的工作的更多信息。

更一般地说,您可以查看Exporter的代码,看看它是如何使用全局别名的。或者,您可以检查模块的命名空间并导出每个子例程。 (我不想在此刻搜索如何执行此操作,但Perl使这相当容易。)或者您可以将子例程放在main包中:

 package main;
 sub firstsub() { ... }

(我认为这不是一个好主意,但你知道的比我想做的更好。)

这样做提供没有任何问题你知道自己在做什么,而不只是试图避免考虑你与外界的接口。

答案 4 :(得分:2)

也许您会对CPAN上的一个Export *模块感兴趣,只需在子定义中添加一个属性,就可以将subs标记为可导出? (不记得是哪一个。)

答案 5 :(得分:2)

https://metacpan.org/pod/Exporter::Auto

导出:自动。这就是你所需要的一切。

答案 6 :(得分:1)

虽然将所有sub从模块转储到调用者名称空间通常并不明智,但有时会自动生成@EXPORT_OK%EXPORT_TAGS个变量(并且更干!)

最简单的方法是扩展Exporter。一个简单的例子是这样的:

package Exporter::AutoOkay;
#
#   Automatically add all subroutines from caller package into the
#   @EXPORT_OK array. In the package use like Exporter, f.ex.:
#
#       use parent 'Exporter::AutoOkay';
#
use warnings;
use strict;
no strict 'refs';

require Exporter;

sub import {
    my $package = $_[0].'::';

    # Get the list of exportable items
    my @export_ok = (@{$package.'EXPORT_OK'});

    # Automatically add all subroutines from package into the list
    foreach (keys %{$package}) {
        next unless defined &{$package.$_};
        push @export_ok, $_;
    }

    # Set variable ready for Exporter
    @{$package.'EXPORT_OK'} = @export_ok;

    # Let Exporter do the rest
    goto &Exporter::import;
}

1;

请注意使用goto将我们从调用者堆栈中删除。

可在此处找到更完整的示例:http://pastebin.com/Z1QWzcpZ它会自动从子例程前缀生成标记组。

答案 7 :(得分:1)

案例1

图书馆是:

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

你可以使用它,调用common :::

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

common::onefunctionthatyoumadeonlibary()

案例2

图书馆,你可以轻松导出它们:

package mycommon;

use strict;
use warnings;

use base 'Exporter';

our @EXPORT = qw(onefunctionthatyoumadeonlibary);
sub onefunctionthatyoumadeonlibary() {
}
1;

在相同的“命名空间”中使用它:

#!/usr/bin/perl
use strict;
use warnings;
use mycommon qw(onefunctionthatyoumadeonlibary);

onefunctionthatyoumadeonlibary()

我们也可以混合使用这两种情况,我们可以导出更常用的函数来使用它,而无需调用包名称和其他函数,我们只用包名称调用它们,而不需要导出它们。

答案 8 :(得分:-1)

你将不得不做一些类型的改变。我在这里描述类似的东西:

Is there a way to "use" a single file that in turn uses multiple others in Perl?

那里的导入例程应该完全符合你的要求 - 只是不要将任何符号导入你自己的命名空间。