Как переименовать экспортированную функцию в Perl? - PullRequest
2 голосов
/ 29 апреля 2009

У меня есть несколько модулей Perl, которые экспортируют различные функции. (Мы не использовали @EXPORT в новых модулях в течение нескольких лет, но сохранили его для совместимости со старыми скриптами.)

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

*directory_error      = *directoryError;

в конце модуля будет просто псевдоним старого имени для нового.

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

Полагаю, что происходит то, что Экспортер готовит список в НАЧАЛЕ, когда псевдоним не был создан; но я попытался поместить назначение typeglob в блок BEGIN, и это не помогло.

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

Какие-нибудь предложения относительно аккуратного способа справиться с этим?

Ответы [ 3 ]

1 голос
/ 01 мая 2009

Экспорт

Вручную вызывать @EXPORT = () вещи становятся немного изможденными.

package Bar;
use strict;
use warnings;

use Sub::Exporter -setup => {
    exports => [qw[ foo ]],
    groups  => {
        default => [qw[ foo ]],
    }
};

sub foo(){

};


1;

Использование:

use strict;
use warnings;
use Bar  foo => { -as-> 'Foo' }; 

Sub :: Exporter может делать много удивительных вещей, таких как экспорт групп, исключение групп, методы компоновщика (т. Е. Как подпрограммы, которые он экспортирует, определяются переданными параметрами, а подпрограммы генерируются внутри других подпрограмм и т. Д.) 1009 *

переименование

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

Затем, когда ваши тесты перестают выдавать предупреждения, вы можете удалить устаревшую функцию.

sub old {  # line 1
   Carp::carp('Legacy function \'old\' called, please move to \'newmethod\' '); 
   goto &newmethod; # this passes @_ literally and hides itself from the stack trace. 
} # line 4

sub newmethod { # line 6
   Carp::cluck('In New Method'); 
   return 5;
} # line 9

print old(), "\n";  # line 11
Legacy function 'old' called, please move to 'newmethod' at code.pl line 2
    main::old() called at code.pl line 11
In New Method at code.pl line 7
    main::newmethod() called at code.pl line 11
5

Обратите внимание, как предупреждения в newmethod выглядят так же, как они были вызваны напрямую.

1 голос
/ 29 апреля 2009

У меня работает следующее. Кажется, это то, что вы описываете; Вы, должно быть, где-то ошиблись.

Основной скрипт:

use strict;
use warnings;
use Bar;

baz();

Модуль:

package Bar;
use strict;
use warnings;

require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(baz);

sub Baz { print "Baz() here\n" }

*baz = *Baz;

1;
0 голосов
/ 29 апреля 2009

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

our @EXPORT = qw(Baz baz);

или

our @EXPORT    = qw(Baz);
our @EXPORT_OK = qw(baz);

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

...