Perl: объяснение, как работает модуль "uni :: perl" - загрузка прагм и других модулей - PullRequest
6 голосов
/ 27 июня 2011

В моем предыдущем вопросе Я спросил, как использовать несколько модулей за одно использование. Получил один идеальный ответ и другой , что указало мне на Modern :: Perl модуль, который действительно прост.

После небольшого поиска в CPAN я нашел другой модуль с именем uni :: perl , что действительно сложно - оно эквивалентно для:

use strict;
use feature qw(say state switch);
no warnings;
use warnings qw(FATAL closed threads internal debugging pack substr malloc
                unopened portable prototype inplace io pipe unpack regexp
                deprecated exiting glob digit printf utf8 layer
                reserved parenthesis taint closure semicolon);
no warnings qw(exec newline);
use utf8;
use open (:utf8 :std);
use mro 'c3';

Может кто-нибудь объяснить / прокомментировать, как это работает?

Я вставил весь код, разделенный на несколько сегментов, и добавил свои вопросы в (###).

Я понимаю, что этот вопрос действительно длинный. Но разделение его на меньшее не поможет, потому что в целом речь идет о модуле "uni :: perl".

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


package uni::perl;
use 5.010;
BEGIN {
    ### OK - these are bitmask of different warnings, they're coming from:
    # paste this into perl to find bitmask 
    # no warnings;
    # use warnings qw(FATAL closed threads internal debugging pack substr malloc unopened portable prototype
    #                 inplace io pipe unpack regexp deprecated exiting glob digit printf
    #                 utf8 layer reserved parenthesis taint closure semicolon);
    # no warnings qw(exec newline);
    # BEGIN { warn join "", map "\\x$_", unpack "(H2)*", ${^WARNING_BITS}; exit 0 };

    ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";
    $^H |= 0x00000602; ### this mean "use strict;"
}

Установка непосредственно ${^WARNING_BITS} и $^H, быстрее, чем обычное «строгое использование» и т. Д.


Что это делает m{ }x.

m{
use strict;
use warnings;
}x;
use mro ();

Я знаю оператор "match" и флаг "x", но не понимаю, что делает в этом контексте ... use mro - это некоторая "темная магия", которую, вероятно, обычные пользователи Perl не должны знать .. .;)


Что означает строка local *__ANON__? Для чего хороша goto в этом контексте? Весь следующий блок BEGIN для меня темная магия. ; (

BEGIN {
    for my $sub (qw(carp croak confess)) {
        no strict 'refs';
        *$sub = sub {    ### for what need replace the global *croak (etc) with this sub?
            my $caller = caller;
            local *__ANON__ = $caller .'::'. $sub;  ### what's mean this?
            require Carp;

                    ### This set the Carp code-refs to the global namespace?
                    ### But who is the "caller" in the BEGIN block? (compile time)

            *{ $caller.'::'.$sub } = \&{ 'Carp::'.$sub };

            goto &{ 'Carp::'.$sub }; ### Why need goto here?
        };
    }
}

Наконец - некоторые более ясные вещи. Перепишите import так, это будет вызвано, когда use uni::perl;

sub import {
    my $me = shift;
    my $caller = caller;

    ### OK - again the bitmasks
    ${^WARNING_BITS} ^= ${^WARNING_BITS} ^ "\xfc\x3f\xf3\x00\x0f\xf3\xcf\xc0\xf3\xfc\x33\x03";


    ### where are these documented?
    $^H |=
          0x00000602 # strict
        | 0x00800000 # utf8
    ;

    # use feature
    $^H{feature_switch} =
    $^H{feature_say}    =
    $^H{feature_state}  = 1;

    # use mro 'c3';
    mro::set_mro($caller, 'c3');

    #use open (:utf8 :std);
    ${^OPEN} = ":utf8\0:utf8";
    binmode(STDIN,   ":utf8");
    binmode(STDOUT,  ":utf8");
    binmode(STDERR,  ":utf8");


    ### again coderef magic. As I understand it - it will replace the
    ### "carp, etc" in the callers namespace with the coderef's defined
    ### in the above BEGIN block. But why with this complicated way?

    for my $sub (qw(carp croak confess)) {
        no strict 'refs';
        *{ $caller .'::'. $sub } = \&$sub;
    }

    ### and finally - I have abosolutely no idea - what do the next code
    ### will take arguments of "use uni::perl qw(arg)"
    ### but have no idea how to use it - or what is doing ;(
    while (@_) {
        my $feature = shift;
        if ($feature =~ s/^://) {
            my $package = $me. '::'. $feature;
            eval "require $package; 1" or croak( "$@" );
            $package->load( $caller );
        }
    }
}

что делает последний while?

Плюс вопрос:

  • почему одни и те же вещи дважды? Один раз в блоке BEGIN и один раз в импорте? (импорт предназначен для «использования» - но зачем делать то же самое в блоке «НАЧАЛО»?

Поскольку этот вопрос состоит из нескольких частей, пожалуйста, укажите соответствующую часть, когда вы даете ответ.

СПАСИБО ВСЕМ В ПРЕДЕЛАХ.

1 Ответ

3 голосов
/ 27 июня 2011
  1. Установка битов предупреждения напрямую выполняется быстрее и имеет более предсказуемое поведение (вы можете видеть все, что должно произойти), но с ним, очевидно, гораздо сложнее работать и поддерживать. Может случиться так, что набор предупреждений, которые uni::perl пытается загрузить, легче сделать с помощью битовых масок.

  2. m{ use strict; use warnings;}x; - это просто регулярное выражение в пустом контексте. Будет выдано сообщение об ошибке или о том, что $_ не установлен, если предупреждения были включены. Я не уверен точно, почему это делается, возможно, нужно успокоить некоторую систему метрик кода, которая ищет строки «используйте предупреждения; используйте строгий». Я бы, наверное, написал это q{...} if 0;, что, по крайней мере, немного яснее.

  3. Этот блок BEGIN создает пользовательские версии функций в Carp. Он использует строку local *__ANON__ = ..., чтобы задать имя любой анонимной подпрограммы, чтобы было легче отслеживать трассировку стека карпа. Блок BEGIN создает упакованные процедуры Carp. Затем подпрограмма импорта загружает эти новые упакованные подпрограммы в пространство имен вызывающего.

  4. Последнее время, похоже, загружает дополнительные модули для uni::perl.

  5. То же самое не делается, см. Ответ на # 3. (BEGIN создает упакованные подпрограммы, import устанавливает их в пространство вызывающего)

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