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 上面 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 是做什么的?

还有问题:

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

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

谢谢大家提前。

时间: 原作者:

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 将它们安装到调用者的空间中)

原作者:
...