2010-03-08 2 views
4

У меня есть модуль Perl, и я хотел бы иметь возможность выбирать параметры, которые мой пользователь моего модуля передал во время «использования». Какие бы я не узнал, я бы хотел пройти. Я попытался сделать это, переопределив метод «импорт», но мне не повезло.проверить параметры «использовать» и передать остальные?

EDIT:

Чтобы уточнить, как это, я могу использовать мой модуль, как это:

use MyModule qw/foo bar/; 

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

use MyModule qw/foo doSpecialStuff bar/; 

и искать doSpecialStuff, чтобы проверить, если мне нужно сделать некоторые специальные вещи в начале программы, а затем передать дш/Foo бар/в экспортера импорт

+0

Пройти на что? Экспортер? Можете ли вы опубликовать код, указывающий, что вы пытаетесь сделать? – mob

+0

Да, Экспортеру. – JoelFan

ответ

8

Обычно, вы могли бы сделать это, чтобы получить импортную функциональность Exporter «s() (это не единственный способ, но это общий метод, который работает):

package MyClass; 
use strict; 
use warnings; 
use Exporter 'import'; # gives you Exporter's import() method directly 
our @EXPORT_OK = qw(stuff more_stuff even_more_stuff); 

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

package MyClass; 
use strict; 
use warnings; 
use parent 'Exporter'; 

sub import 
{ 
    my ($class, @symbols) = @_; 

    # do something with @symbols, as appropriate for your application 
    # ...code here left as an exercise for the reader :) 

    # now call Exporter's import, and import to the right level 
    local $Exporter::ExportLevel = 1; 
    $class->SUPER::import(@symbols); 
} 

Однако, я задаюсь вопросом, почему вам нужно сделать, это ... стандартное поведение смерти, когда передается непризнанный символ, как правило, хорошая вещь. Почему вы хотите игнорировать непризнанные символы? (Редактировать: Теперь я хочу указать дополнительное поведение поверх импорта символов, что не является чем-то необычным в Perl. Поэтому определение собственного метода import() - это, безусловно, путь сюда, чтобы захватить эти значения.)


PS. если вы только хотите импортировать символы, которые определяются @EXPORT_OK, она может быть реализована следующим образом:

@symbols = grep { 
    my $sym = $_; 
    grep { $_ eq $sym } @EXPORT_OK 
} @symbols; 

+0

ОК классно! Теперь, какой лучший способ выбрать символы, которые я узнаю и оставлю все остальное? Греп, похоже, не соответствует законопроекту. – JoelFan

+0

Непризнанные символы не игнорируются, они просто передаются «Экспортеру», где они будут убивать скрипт, если они остаются нераспознанными. – mob

+0

Я не хочу игнорировать непризнанные символы ... Я хочу обработать их, а затем удалить их. – JoelFan

3

Типичное использование Exporter является объявить свой модуль, чтобы наследовать от Exporter, и для использования метода Exporterimport, который неявно используется при использовании вашего модуля. Но это не дает вам создать собственный метод import для вашего модуля.

Обходным методом является использование метода export_to_level экспортера, который выполняет функции Exporter без явного прохождения метода Exporter::import.Вот типичный способ использовать:

package My::Module; 
use base 'Exporter'; # or use Exporter; our @ISA=qw(Exporter); 
our @EXPORT = qw(...); 
our @EXPORT_OK = qw(...); 
our %EXPORT_TAGS = (...); 

sub import { 
    my ($class,@import_args) = @_; 
    my @import_args_to_pass_on =(); 
    foreach my $arg (@import_args) { 
     if (... want to process this arg here ...) { 
      ... 
     } else { 
      push @import_args_to_pass_on, $arg; 
     } 
    } 
    My::Module->export_to_level(1, "My::Module", @import_args_to_pass_on, @EXPORT); 
    #or: $class->export_to_level(1, $class, @import_args_to_pass_on, @EXPORT); 
} 
+0

Спасибо ... за любую причину предпочесть это решение более простому с помощью «ehter» выше? – JoelFan

+0

@Joel: Я думаю, что в этом случае они эквивалентны. В документах экспортера говорится: «[use]« export_to_level »... в ситуациях, когда вы не можете напрямую вызвать метод импорта Экспортера», который, похоже, не здесь, но он определенно работает так же хорошо, как и в другом случае. это просто дольше. :) – Ether

+0

@Joel, я пытаюсь использовать код Эфера, но я не могу заставить его работать. Возможно, я ничего не делаю правильно, но методы, которые я хочу экспортировать, не отображаются в главной таблице символов. – mob

2

Я сделал это так в моих модулях:

sub import { 
    return if not @_; 
    require Exporter; 
    my $pkg = shift; 

    # process @_ however you want 

    unshift @_, $pkg; 
    goto &Exporter::import; 
} 

вы можете наследовать от экспортера, если вы хотите unimport и тому подобное.

+0

умный - шаги в 'Экспортер :: импорт', но не подталкивает новый фрейм к стеку (так что возвращаемые значения из' caller' не затрагиваются). Вы не можете поместить какой-либо код после инструкции 'goto' и до конца метода, хотя (знаете, если вы этого хотели). – mob

+0

Perl's goto сложный, но иногда это может быть удобно! (если вы знаете, что делаете) :) – Ether