perl - Perl: 解释如何工作"uni:: Perl"模块加载杂注和其他模块

  显示原文与译文双语对照的内容
66 2

在我的pervious问题我问了如何使用多个模块。我的一个完美答案是,而又我Modern::Perl 模块 what 。

在一点搜索之后,我找到了另一个名为 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} ^"xfcx3fxf3x00x0fxf3xcfxc0xf3xfcx33x03";
 $^H |= 0x00000602; ### this mean"use strict;"
}

直接设置 ${^WARNING_BITS}$^H,比普通的"使用严格"和要快?

这个 m{ }x 做什么。

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

我知道"匹配"操作符和'x'标志,但是不明白在这个上下文中做了什么。use mro 是一些"黑魔法",可能是普通perl用户不需要知道的。; )

local *__ANON__ 行是什么?关于这个上下文中的goto 是什么?下一个开始块对我来说是个黑魔法。;(

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} ^"xfcx3fxf3x00x0fxf3xcfxc0xf3xfcx33x03";
 ### 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: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 是做什么的?

还有问题:

  • 为什么同样的事情两次?在开始块中一次,在导入中一次?( 导入用于"用户"- 但是为什么在"开始"块中做同样的事情?

因为这个问题有更多的部分,请在给出答案时引用相关的部分。

谢谢大家提前。

时间:原作者:0个回答

65 4

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

m{ use strict; use warnings;}x;在void上下文中只是一个 正规表达式 。它将引发一个错误,无论是否启用了警告,都不会设置上下文或者 $_我不确定为什么这么做,它可以能是为了满足一些代码制度系统,查找行"使用警告;使用严格"。我可能已经写了 q{...} if 0;,它至少更清晰一点。

这个开始块正在创建Carp中函数的自定义版本。它正在使用local *__ANON__ =.. .line设置匿名子程序的名称,以便Carp堆栈跟踪更容易跟踪。开始块创建被包装的Carp例程。导入子程序然后将这些新的打包例程加载到调用方的命名空间中。

最后,似乎正在为 uni::perl 加载额外的插件模块。

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

原作者:
...