Ответ 1
Не выполняйте экспорт вообще и не объявляйте имя пакета в своей библиотеке. Просто загрузите файл с помощью require
, и все будет в текущем пакете. Легкий peasy.
Я хотел бы разоблачить все подсайты в моем пространстве имен, не указывая их по одному за раз:
@EXPORT = qw( firstsub secondsub third sub etc );
Использование полных имен потребует кучи изменения существующего кода, поэтому я бы предпочел не делать этого.
Есть ли @EXPORT_ALL?
Я думаю, что документация говорит, что это плохая идея, но я бы хотел сделать это в любом случае или, по крайней мере, знать, как это сделать.
Чтобы ответить Джону, почему: прямо сейчас для быстрого рефакторинга я хочу переместить кучу подписчиков в свой собственный пакет с минимальными переменами и изменениями кода в существующих сценариях (где эти подсистемы используются и часто повторяются).
Кроме того, в основном, мне было просто любопытно. (поскольку казалось, что Экспортер также может иметь это стандартное свойство, но несколько удивительно основанное на ответах до сих пор не делает этого)
Не выполняйте экспорт вообще и не объявляйте имя пакета в своей библиотеке. Просто загрузите файл с помощью require
, и все будет в текущем пакете. Легкий peasy.
не делать. Но если вы действительно хотите... написать пользовательский 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 };
}
}
Предупреждение. Следующий код - это плохая идея экспортировать все:
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
Вы всегда можете вызывать подпрограммы в полностью заданной форме:
MyModule::firstsub();
Для модулей, которые я пишу внутренне, я считаю, что это соглашение работает достаточно хорошо. Это немного больше печатает, но имеет тенденцию быть лучшей документацией.
Взгляните на perldoc perlmod
для получения дополнительной информации о том, что вы пытаетесь выполнить.
В более общем плане вы можете посмотреть код Exporter
и посмотреть, как он использует сглаживание glob. Или вы можете проверить пространство имен модулей и экспортировать каждую подпрограмму. (Я не хочу искать, как это сделать в данный момент, но Perl делает это довольно легко.) Или вы можете просто придерживать свои подпрограммы в пакете main
:
package main;
sub firstsub() { ... }
(Я не думаю, что это хорошая идея, но вы знаете лучше, чем я делаю то, что вы пытаетесь выполнить.)
Нет ничего плохого в этом при условии, что вы знаете, что делаете, и не просто пытаетесь не думать о своем интерфейсе во внешнем мире.
Возможно, вас будет интересовать один из модулей Export * в CPAN, который позволяет вам маркировать subs как экспортируемое просто путем добавления атрибута к суб определению? (Не помните, какой из них был.)
https://metacpan.org/pod/Exporter::Auto
экспортёр:: Авто. это все, что вам нужно.
Хотя обычно не рекомендуется сбрасывать все sub
из модуля в пространство имен вызывающего абонента, иногда полезно (и более DRY!) автоматически генерировать переменные @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 Он автоматически генерирует группы тегов из префиксов подпрограмм.
Библиотека:
package mycommon;
use strict;
use warnings;
sub onefunctionthatyoumadeonlibary() {
}
1;
вы можете использовать его, вызывая общий:
#!/usr/bin/perl
use strict;
use warnings;
use mycommon;
common::onefunctionthatyoumadeonlibary()
Библиотека, вы просто экспортируете их:
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()
Также мы можем сделать сочетание этих двух случаев, мы можем экспортировать более общие функции, чтобы использовать его, не вызывая имя пакета и другие функции, которые мы называем только с именем пакета, и что их не нужно экспортировать.
Вам нужно будет немного манипулировать типом. Я описываю здесь нечто подобное:
Процедура импорта должна делать именно то, что вы хотите - просто не импортируйте никакие символы в свое собственное пространство имен.