22

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

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

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

有@EXPORT_ALL 吗?

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

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

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

4

9 回答 9

24

根本不要进行任何导出,也不要在你的库中声明包名。只需加载文件,require所有内容都将在当前包中。十分简单。

于 2009-04-08T23:58:35.647 回答
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 };
    }
}
于 2009-04-09T00:15:10.927 回答
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
于 2009-04-08T23:09:30.710 回答
2

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

MyModule::firstsub();

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

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

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

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

(我认为这不是一个好主意,但你比我更清楚你想要完成的事情。)

如果您知道自己在做什么,并且不只是试图避免考虑与外界的接口,那么这样做并没有错。

于 2009-04-08T22:33:36.130 回答
2

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

于 2009-04-09T01:29:04.413 回答
2

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

出口商::汽车。这就是你所需要的。

于 2014-10-11T18:23:01.537 回答
1

虽然将模块中的所有 s 转储到调用者命名空间通常不是明智之举,但自动生成和变量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它自动从子程序前缀生成标签组。

于 2013-04-02T00:32:25.440 回答
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()

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

于 2013-11-14T21:38:06.830 回答
-1

你将不得不做一些 typeglob munging。我在这里描述了类似的东西:

有没有办法“使用”单个文件,然后在 Perl 中使用多个其他文件?

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

于 2009-04-08T22:47:28.670 回答