Подтвердить что ты не робот

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

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

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

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

Есть ли @EXPORT_ALL?

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

не делать. Но если вы действительно хотите... написать пользовательский 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 };
    }
}

Ответ 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

Ответ 4

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

MyModule::firstsub();

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

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

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

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

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

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

Ответ 5

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

Ответ 7

Хотя обычно не рекомендуется сбрасывать все 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 Он автоматически генерирует группы тегов из префиксов подпрограмм.

Ответ 8

случай 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()

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

Ответ 9

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

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

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