Как экспортировать переменные только для чтения с помощью mod_perl? - PullRequest
3 голосов
/ 10 апреля 2009

Я пытаюсь упростить выполнение некоторых Perl Best Practices , создав модуль Constants, который экспортирует несколько скаляров, использованных в книге. Один из них, $EMPTY_STRING, я могу использовать практически в каждом скрипте Perl, который я пишу. Я хотел бы автоматически экспортировать эти скаляры, чтобы я мог использовать их, не определяя их явно в каждом скрипте.

#!perl
package Example::Constants;

use Exporter qw( import );
use Readonly;

Readonly my $EMPTY_STRING => q{};
our @EXPORT = qw( $EMPTY_STRING );

Пример использования:

#!perl
use Example::Constants;
print $EMPTY_STRING . 'foo' . $EMPTY_STRING;

Использование приведенного выше кода приводит к ошибке:

Global symbol "$EMPTY_STRING" requires explicit package name

Если я изменю объявление Readonly на:

Readonly our $EMPTY_STRING => q{}; # 'our' instead of 'my'

Ошибка становится:

Attempt to reassign a readonly scalar

Это просто невозможно с mod_perl?

Ответы [ 3 ]

4 голосов
/ 14 апреля 2009

Я являюсь автором модуля Readonly. Следующая версия Readonly обеспечит поддержку mod_perl, особенно из-за этой проблемы.

Я знаю, что это не решит твою проблему сейчас , но ... хорошо, я работаю над этим: -)

- Эрик

3 голосов
/ 10 апреля 2009

У вас было 4 проблемы:

  1. Вы не включали strict и warnings прагмы
  2. Лучше включить экспортер с помощью прагмы base (поскольку он устанавливает для вас @ISA)
  3. Можно экспортировать только переменные пакета (т.е. our переменные)
  4. Модули должны заканчиваться истинным значением

Вот исправленный модуль.

package Example::Constants;

use strict;
use warnings;
use base 'Exporter';
use Readonly;

Readonly our $EMPTY_STRING => q{};
our @EXPORT = qw( $EMPTY_STRING );

1;

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

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

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

Попробуйте использовать Scalar::Util::readonly, чтобы проверить, помечена ли уже переменная только для чтения.

#!perl
package Example::Constants;

use Exporter qw( import );
use Readonly;
use Scalar::Util qw(readonly);

our $EMPTY_STRING;
our @EXPORT = qw( $EMPTY_STRING );

if ( !readonly( $EMPTY_STRING ) ) {
    Readonly $EMPTY_STRING => q{};
}

Вы также можете попробовать use vars:

#!perl
package Example::Constants;

use Exporter qw( import );
use Readonly;
use vars qw( $EMPTY_STRING );

Readonly $EMPTY_STRING => q{};
our @EXPORT = qw( $EMPTY_STRING );

Вы также можете использовать константу typeglob:

#!perl
package Example::Constants;

use Exporter qw( import );
use Readonly;

our $EMPTY_STRING;
*EMPTY_STRING = \q{};
our @EXPORT = qw( $EMPTY_STRING );

Использование константы typeglob кажется идеальным, поскольку большое ограничение метода (для него требуется глобальный пакет) здесь не является проблемой.

...