Perl - Проблемы Пакета/Модуля

От всего я читал при использовании модулей Perl, основное использование:

  • Файл модуля с .pm расширение, которое включает оператор package <name>, где <name> имя файла модуля без расширения.
  • Файл кода, который использует модуль, содержит оператор use <name>;.

Приложение, которое я кодирую, имеет один основной сценарий кода, который использует приблизительно 5 модулей. Я забыл включать package <name> оператор в модулях, но мой код все еще работал очень хорошо с use <name> оператор. Я начал получать Undefined subroutine ошибки с одним из модулей, таким образом, я добавил оператор пакета к каждому из модулей. Теперь остальная часть тех модулей прекратила работать. Что дает?

Пример:

mainapp.pl

#!/usr/bin/perl
use UtyDate;
my $rowDate = CurrentDate("YYYYMMDD");

UtyDate.pm

#!/usr/bin/perl
package UtyDate;
sub CurrentDate
{
    #logic
}
return 1;

Когда я выполняю вышеупомянутый код, я получаю ошибку Undefined subroutine &main::CurrentDate called at.... Однако, если я удаляю package UtyDate; строка от UtyDate.pm, я не получаю ошибки. Эта ситуация существует для нескольких, но не всех моих модулей.

Существует, очевидно, намного больше кода, который я не показываю, но я смущен, как любой код, который я не показываю, мог влиять на конструкции пакета/использования, которые я показал здесь.

7
задан daxim 21 June 2010 в 14:04
поделиться

4 ответа

Когда вы используете модуль, его код запускается во время компиляции. Затем вызывается импорт имени пакета для модуля. Итак, используйте Foo; то же самое, что BEGIN {require Foo; Foo-> импорт; }

Ваш код работал без объявлений package , потому что весь код выполнялся в пакете main , который используется основным кодом приложения.

Когда вы добавили объявления пакета , он перестал работать, потому что определенные вами подпрограммы больше не определены в main , а в UtyDate .

Вы можете получить доступ к подпрограммам, используя полное имя UtyDate :: CurrentDate (); , или импортируя подпрограммы в текущее пространство имен, когда вы используете модуль.

UtyDate.pm

package UtyDate;
use strict;
use warnings; 

use Exporter 'import';

# Export these symbols by default.  Should be empty!    
our @EXPORT = ();

# List of symbols to export.  Put whatever you want available here.
our @EXPORT_OK = qw( CurrentDate  AnotherSub ThisOneToo );

sub CurrentDate {
    return 'blah';
}

sub AnotherSub { return 'foo'; }

Основная программа:

#!/usr/bin/perl
use strict;
use warnings; 

use UtyDate 'CurrentDate';

# CurrentDate is imported and usable.    
print CurrentDate(), " CurrentDate worked\n";

# AnotherSub is not
eval {  AnotherSub() } or print "AnotherSub didn't work: $@\n";

# But you can still access it by its fully qualified name
print UtyDate::AnotherSub(), " UtyDate::AnotherSub works though\n";

Дополнительную информацию см. В документации Exporter .

10
ответ дан 6 December 2019 в 15:19
поделиться

Вам не хватает кода заголовка perl экспортера. Вам нужно добавить что-то вроде следующего в верхнюю часть вашего pm-файла под утверждением о пакете:

package UtyDate;
BEGIN {
  use Exporter ();
  use vars qw($VERSION @ISA @EXPORT);
  $VERSION = "1.0.0";
  @ISA = qw(Exporter);
  @EXPORT = qw( &CurrentDate );
}

См. эту ссылку: http://perldoc.perl.org/Exporter.html#DESCRIPTION

3
ответ дан 6 December 2019 в 15:19
поделиться

В качестве альтернативы предложению Грея можно сделать следующее:

use UtyDate;
UtyDate::CurrentDate(...);
1
ответ дан 6 December 2019 в 15:19
поделиться

Кроме использования экспортера, как указывает Грей, вы можете (UGLY, но работает) также вызывать функции с именем модуля ...

Вы functiond/procedures не работают, поскольку они теперь находятся в другом пространстве имен (определенном именем модуля)

use UtyDate;

UtyDate::CurrentDate(  )
0
ответ дан 6 December 2019 в 15:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: