Как мне экспортировать функцию с именем 'import' из модуля в Perl? - PullRequest
4 голосов
/ 26 июля 2010

Я написал специальную функцию импорта, которая будет использоваться в нескольких местах, и я хотел бы иметь возможность просто "использовать ImportRenamer;" в этих модулях и пусть они используют импорт, полученный от ImportRenamer впредь. Как бы я поступил об этом?

Редактировать: Другими словами: как импортировать «импорт» без его запуска?

Ответы [ 4 ]

3 голосов
/ 27 июля 2010

В качестве альтернативы, вы можете избежать просмотра в таблице символов, используя Sub :: Exporter

package Your::Module;

use Sub::Exporter (
    -setup => {
        exports => {
            import => sub { return \&_real_import }
        },
        # the "default" group auto-exports "import" without the caller 
        # specifically asking for it
        groups => { default => [qw(import)] },
    }
);

sub _real_import { ... }

РЕДАКТИРОВАТЬ: добавлено "по умолчанию"группа для автоэкспорта

3 голосов
/ 27 июля 2010

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

Вот некоторый непроверенный код:

package ImportMe;

sub import { 

    # Get package name
    my $caller = caller;

    # Install my_import into the calling package as import
    {    no strict 'refs';
         *{"${caller}::import"} = \&my_import;
    }

    return 1;
}

# renamed as import when installing
sub my_import {

   # do stuff

}

Теперь вы можете поместить use ImportMe; во все ваши модули, и будет установлен метод import.

3 голосов
/ 26 июля 2010

UPDATE

Теперь, когда OP прояснил свои потребности, это действительно должно быть сделано способом, аналогичным тому, что делает Exported, если быть точным, путем вставки вспомогательной ссылки в пространство имен вызывающей стороны посредством назначения glob. Пример:

###############################################

package ImportRenamer; 
use strict;
sub import_me {
   print "I am a cool importer\n";
}

sub import { 
  my ($callpkg)=caller(0);
  print "Setting ${callpkg}::import to ImportRenamer::import_me\n"; 
  no strict "refs";
  *{$callpkg."::import"} = \&ImportRenamer::import_me; # Work happens here!!!
  use strict "refs";
}
1;

###############################################

package My; 
use strict;
use ImportRenamer; 
1;

###############################################

package My2; 
use strict;
use ImportRenamer; 
1;

###############################################

И тест:

> perl -e '{  package main; use My; use My2; 1;}'
Setting My::import to ImportRenamer::import_me
I am a cool importer
Setting My2::import to ImportRenamer::import_me
I am a cool importer

ОРИГИНАЛЬНЫЙ ОТВЕТ

Вам не нужно делать ничего особенного, кроме вызова метода импорта "import". use уже звонит import(), см. использование perldoc :

use Module LIST 

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

Это в точности эквивалентно:

 BEGIN { require Module; Module->import( LIST ); }
2 голосов
/ 27 июля 2010

Примерно так:

package Your::Module;

use strict;
use warnings;

sub import { 
    # gets called by use Your::Module
    my ( $pkg ) = caller;

    no strict 'refs';
    *{ $pkg . '::import' } = \&_real_import;
}

sub _real_import { 
    # import function to be exported to caller
    print "blah blah";
}

Это вручную присваивает подпрограмму _real_import для слота import пространства имен вызывающего пакета.Если вы сделаете это в блоке BEGIN, то сабвуфер import должен быть готов и ждать, когда этот пакет получит use d.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...