Как я могу экспортировать все подпрограммы в пакете Perl?

18

Я хотел бы выставить все подпрограммы в мое пространство имен без необходимости перечислять их по одному:

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

Использование полностью определенных имен потребовало бы внесения множества изменений в существующий код, поэтому я бы предпочел этого не делать.

Есть ли @EXPORT_ALL?

Я думаю, что документация говорит, что это плохая идея, но я все равно хотел бы сделать это или, по крайней мере, знать, как.

Чтобы ответить на вопрос Джона: сейчас, для быстрого рефакторинга, я хочу переместить группу подпрограмм в их собственный пакет с наименьшими хлопотами и изменениями кода в существующих сценариях (где эти подпрограммы в настоящее время используются и часто повторяются).

Кроме того, в основном мне было просто любопытно. (так как казалось, что Exporter с таким же успехом может иметь это в качестве стандартной функции, но, на удивление, основывается на ответах, которых пока нет)

    
задан Ville M 09.04.2009 в 00:25
источник
  • Может быть, если вы могли бы сообщить нам, почему вы хотите это сделать. Просто для пинков? –  Jon Ericson♦ 09.04.2009 в 01:15
  • ОК, добавил почему. –  Ville M 09.04.2009 в 01:23

9 ответов

22

Не делайте никакого экспорта и не объявляйте имя пакета в вашей библиотеке. Просто загрузите файл с require , и все будет в текущем пакете. Легко peasy.

    
ответ дан brian d foy 09.04.2009 в 01:58
  • Отличный ответ! –  Ville M 09.04.2009 в 02:05
  • Doh! Я все время танцевал вокруг этого решения, не задумываясь об этом. (Но это нарушает ожидания того, что модуль будет иметь собственное пространство имен, что может удивить.) –  Jon Ericson♦ 09.04.2009 в 02:09
  • Как мне «загрузить» файл? –  Ville M 09.04.2009 в 02:25
  • ОК, получил его, изменил использование. то есть. do "mymod.pm"; –  Ville M 09.04.2009 в 02:36
  • @VilleM требует! do перезагружает модуль каждый раз, когда он вызывается. требуют только нагрузки один раз. –  Schwern 09.04.2009 в 18:49
Показать остальные комментарии
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 };
    }
}
    
ответ дан Michael Carman 09.04.2009 в 02:15
  • Также см. ответ Леона в stackoverflow.com/questions/607282/... –  brian d foy 09.04.2009 в 02:32
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
    
ответ дан Chas. Owens 09.04.2009 в 01:09
  • Великолепно, именно то, что я надеялся, стандартного способа в экспортере, я думаю, но это определенно делает то, что мне нужно, большое спасибо –  Ville M 09.04.2009 в 01:14
  • Я думаю, что просто прохожу через таблицу символов и буду искать определенные записи кода. Слишком много способов, с помощью которых может выполняться регулярное выражение. –  brian d foy 09.04.2009 в 01:58
  • Не могли бы вы рассказать о том, как «пройти через таблицу символов»? –  Ville M 09.04.2009 в 02:02
  • Да, поэтому я поставил там предостережение, что это была плохая идея. Это был самый простой способ, о котором я мог думать, и если это вызывает проблемы, ну, в первую очередь, это не должно было быть сделано. –  Chas. Owens 09.04.2009 в 02:13
  • Не пытайтесь разбирать код Perl, / usr / bin / perl уже сделал это за вас. –  hillu 09.04.2009 в 11:41
2

Вы всегда можете вызвать подпрограммы в полностью указанной форме:

MyModule::firstsub();

Для модулей, которые я пишу внутри, я считаю, что это соглашение работает довольно хорошо. Это немного больше печатает, но лучше документация.

Посмотрите на perldoc perlmod для получения дополнительной информации о том, чего вы пытаетесь достичь.

В общем, вы можете посмотреть на код Exporter и посмотреть, как он использует псевдонимы глобусов. Или вы можете проверить пространство имен вашего модуля и экспортировать каждую подпрограмму. (Я не хочу искать, как это сделать в данный момент, но Perl делает это довольно легко.) Или вы можете просто вставить свои подпрограммы в пакет main :

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

(Я не думаю, что это хорошая идея, но вы знаете лучше, чем я, что вы пытаетесь достичь.)

Нет ничего плохого в том, чтобы при условии, что вы знаете, что делаете, и не просто пытаетесь не думать о своем интерфейсе с внешним миром.

    
ответ дан Jon Ericson 09.04.2009 в 00:33
  • Да, я знаю об этом, но как насчет того, чтобы не сказать MyModule :: для каждого суб? Я ищу ЭКСПОРТ ВСЕ? –  Ville M 09.04.2009 в 00:37
  • @Ville M: ​​Часто бывает трудно узнать, что кто-то знает, если они этого не говорят. ;-) –  Jon Ericson♦ 09.04.2009 в 00:53
  • Что-то о звуке и падении дерева в лесу приходит в голову ... в любом случае, спасибо за вашу помощь –  Ville M 09.04.2009 в 01:12
2

Возможно, вас заинтересует один из модулей Export * в CPAN, который позволяет пометить подпрограммы как экспортируемые, просто добавив атрибут в определение? (Хотя не помню, какой именно.)

    
ответ дан ysth 09.04.2009 в 03:29
  • было этим, о чем вы думали? search.cpan.org/dist/Exporter-NoWork/lib/Exporter/NoWork.pm –  Chas. Owens 09.04.2009 в 15:45
  • @ Час. Оуэнс - нет, я думал об Экспортере :: Простой –  ysth 12.04.2009 в 07:50
2

Ссылка

экспортёр :: Авто. это все, что вам нужно.

    
ответ дан echo 11.10.2014 в 20:23
1

Хотя обычно нецелесообразно выгружать все sub s из модуля в пространство имен вызывающей стороны, иногда полезно (и более DRY!) автоматически генерировать переменные @EXPORT_OK и %EXPORT_TAGS .

Самый простой способ - расширить экспортер. Простой пример примерно такой:

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 , которое удаляет нас из стека вызывающих.

Более полный пример можно найти здесь: Ссылка . Он автоматически генерирует группы тегов из префиксов подпрограмм.

    
ответ дан Tero Niemi 02.04.2013 в 02:32
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()

Также мы можем сделать смесь этих двух случаев, мы можем экспортировать более общие функции, чтобы использовать их без вызова имени пакета и других функций, которые мы вызываем только с именем пакета, и которые не нужно экспортировать.     

ответ дан Sérgio 14.11.2013 в 22:38
-1

Тебе нужно будет сделать несколько манипуляций с typeglob. Я опишу нечто подобное здесь:

Есть ли способ" использовать "один файл, который, в свою очередь, использует несколько других в Perl?

Процедура импорта там должна делать именно то, что вы хотите - только не импортируйте символы в свое собственное пространство имен.

    
ответ дан jrockway 09.04.2009 в 00:47