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

18

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

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

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

Есть ли @EXPORT_ALL?

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

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

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

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

9 ответов

23

Не выполняйте экспорт вообще и не объявляйте имя пакета в своей библиотеке. Просто загрузите файл 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]+)/ ?  : () } <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 и посмотреть, как он использует сглаживание glob. Или вы можете проверить пространство имен вашего модуля и экспортировать каждую подпрограмму. (Я не хочу искать, как это сделать в данный момент, но 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, который позволяет вам маркировать subs как экспортируемое просто путем добавления атрибута к суб определению? (Не помните, какой из них был.)

    
ответ дан 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 .

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

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

    
ответ дан Tero Niemi 02.04.2013 в 02:32
источник
1

случай 1

Библиотека:

package mycommon;

use strict;
use warnings;

sub onefunctionthatyoumadeonlibary() {
}
1;

вы можете использовать его, вызывая общий :::

#!/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

Вам нужно будет немного манипулировать типом. Я описываю здесь нечто подобное:

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

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

    
ответ дан jrockway 09.04.2009 в 00:47
источник