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

В моем вопросе прошивки я спросил, как использовать несколько модулей с одним использованием. Получил один отличный ответ и еще один, что указывало мне на 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} a $^H, быстрее, чем обычная "use strict" и т.д.


Что делает это 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 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 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( "[email protected]" );
            $package->load( $caller );
        }
    }
}

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

Плюс вопрос:

  • зачем делать то же самое в два раза? Один раз в блоке BEGIN и один раз в импорте? (импорт предназначен для "использования" - но зачем делать почти то же самое в блоке "BEGIN"?

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

СПАСИБО ВАМ ВСЕ ПРЕДУСМОТРЕТЬ.

Ответ 1

  • Настройка битов предупреждения выполняется немного быстрее и имеет более предсказуемое поведение (вы можете видеть все, что должно произойти), но с этим, очевидно, гораздо труднее работать и поддерживать. Может случиться так, что набор предупреждений, которые пытается загружать uni::perl, проще выполнять через битмаски.

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

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

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

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