【问题标题】:Perl: explanation how to works the "uni::perl" module - loading pragmas and other modulesPerl:解释如何使用“uni::perl”模块 - 加载编译指示和其他模块
【发布时间】:2011-09-23 13:28:32
【问题描述】:

在我的pervious question 中,我询问了如何一次使用多个模块。有一个 perfect answer 和 another one 指向我的 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,比普通的“use strict”等更快吗?


这是在做什么m{ }x。

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

我知道“匹配”运算符和“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 块中,一次在导入中? (导入是为了“使用”——但是为什么在“开始”块中也做几乎相同的事情呢?

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

提前谢谢大家。

【问题讨论】:

    标签: perl


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

    2. m{ use strict; use warnings;}x; 只是 void 上下文中的正则表达式。如果启用了警告,它将引发有关上下文或 $_ 未设置的错误。我不确定这样做的确切原因,可能是为了安抚一些代码度量系统,该系统查找“使用警告;使用严格”行。我可能会写它q{...} if 0;,这至少更清楚一点。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 2012-07-26
      • 2011-04-29
      • 2013-02-04
      • 2011-05-16
      • 1970-01-01
      相关资源
      最近更新 更多