Perl:解释如何使用“uni::perl";模块 - 加载编译指示和其他模块 [英] Perl: explanation how to works the "uni::perl" module - loading pragmas and other modules

查看:49
本文介绍了Perl:解释如何使用“uni::perl";模块 - 加载编译指示和其他模块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的上一个问题中,我询问了如何一次使用多个模块.得到了一个完美答案,并且另一个是什么让我看到了Modern::Perl 模块真的很简单.

In my pervious question I asked how to use multiple modules with one use. Got one perfect answer, and another one what pointed me to Modern::Perl module what is really simple.

在对 CPAN 进行了一番搜索后,我发现了另一个名为 uni::perl,真正复杂的是什么 - 它是并且等效于:

After a bit searching CPAN I found another module called uni::perl, what is really complicated - it is and equivalent for:

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';

有人可以解释/评论它的工作原理吗?

我将整个代码粘贴在这里,分成几个部分并将我的问题添加到,(使用###).

I pasted the whole code here divided into few segments and added my questions into, (with ###).

我明白这个问题真的很长.但是,把它分成更小的一个也无济于事,因为整体是关于uni::perl"模块的.

I understand than this question is really long. But, dividing it into smaller one will not help, because the whole is about the "uni::perl" module.

请帮助我理解有问题的部分.

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,比常见的use strict"等更快?

Setting directly the ${^WARNING_BITS} an the $^H, is faster than a common "use strict" and etc?

这是做什么的m{ }x.

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

我知道匹配"运算符和x"标志,但不明白在这种情况下在做什么.. use mro 是一些黑暗魔法",可能是普通 perl 用户不知道的不需要知道...;)

I know the "match" operator and 'x' flag but not understand what is doing in this context.. use mro is some "dark-magic" what probably an common perl users don't need to know... ;)

local *__ANON__ 行有什么作用?在这种情况下 goto 有什么好处?整个下一个 BEGIN 块对我来说是一个黑魔法.;(

What's do the local *__ANON__ line? For what is good the goto in this context? The whole next BEGIN block is an dark magic for me. ;(

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 块中,一次在导入中?(导入是为了使用"——但为什么在开始"块中也做几乎相同的事情?

由于本题部分较多,请在回答时引用相关部分.

Because this question has more parts, please, quote the relevant part when you giving an answer.

提前谢谢大家.

推荐答案

  1. 直接设置警告位会更快一些,并且具有更多可预测的行为(您可以看到应该发生的一切),但显然更难使用和维护.uni::perl 尝试加载的警告集可能通过位掩码更容易完成.

  1. Setting the warning bits directly is a bit faster, and has more predictable behavior (you can see everything that should happen), but it is obviously much harder to work with and maintain. It may be that the set of warnings that uni::perl is trying to load is easier done through the bitmasks.

m{ 使用严格;use warnings;}x; 只是 void 上下文中的正则表达式.如果启用了警告,它将抛出关于上下文或 $_ 未设置的错误.我不确定为什么要这样做,这可能是为了安抚一些寻找使用警告;使用严格"行的代码度量系统.我可能会写它 q{...} if 0; 至少更清楚一点.

m{ use strict; use warnings;}x; is simply a regex in void context. It would throw an error either about context or $_ not being set if warnings were enabled. I am not sure exactly why this is being done, it might be to appease some code metric system that looks for the lines "use warnings; use strict". I would have probably written it q{...} if 0; which is at least a little clearer.

这个 BEGIN 块正在创建 Carp 中函数的自定义版本.它使用 local *__ANON__ = ... 行来设置任何匿名子例程的名称,以便更容易跟踪 Carp 堆栈跟踪.BEGIN 块创建封装的 Carp 例程.然后导入子例程将这些新包装的例程加载到调用者的命名空间中.

This BEGIN block is creating custom versions of the functions in Carp. It is using the local *__ANON__ = ... line to set the name of any anonymous subroutines so that the Carp stack trace is easier to follow. The BEGIN block creates the wrapped Carp routines. The import subroutine then loads these new wrapped routines into the caller's namespace.

最后一段时间似乎正在为 uni::perl 加载额外的插件模块.

That last while seems to be loading additional plugin modules for uni::perl.

没有做同样的事情,请参阅 #3 的答案.(BEGIN 创建包装的例程,import 将它们安装到调用者的空间中)

The same thing is not being done, see the answer to #3. (BEGIN creates the wrapped routines, import installs them into the caller's space)

这篇关于Perl:解释如何使用“uni::perl";模块 - 加载编译指示和其他模块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆