在我以前的问题中,我问过如何使用多个模块.得到了一个完美的答案,另一个指向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';
Run Code Online (Sandbox Code Playgroud)
有人可以解释/评论它是如何工作的吗?
我将整个代码粘贴到几个部分,并将我的问题添加到(with ###)中.
我明白这个问题真的很长.但是,将它分成更小的一个将无济于事,因为整体是关于"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;"
}
Run Code Online (Sandbox Code Playgroud)
直接设置${^WARNING_BITS}一个$^H,比普通的"使用严格"等快?
这是做什么的m{ }x.
m{
use strict;
use warnings;
}x;
use mro ();
Run Code Online (Sandbox Code Playgroud)
我知道"匹配"运算符和'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?
};
}
}
Run Code Online (Sandbox Code Playgroud)
最后 - 一些更清楚的事情.重写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 );
}
}
}
Run Code Online (Sandbox Code Playgroud)
最后做了while什么?
加上问题:
因为这个问题有更多部分,请在给出答案时引用相关部分.
谢谢大家.
直接设置警告位会更快一些,并且具有更可预测的行为(您可以看到应该发生的所有情况),但显然使用和维护起来要困难得多。uni::perl尝试加载的警告集可能通过位掩码更容易完成。
m{ use strict; use warnings;}x;只是 void 上下文中的正则表达式。$_如果启用警告,它会抛出有关上下文或未设置的错误。我不确定为什么要这样做,可能是为了安抚一些寻找“使用警告;使用严格”行的代码度量系统。我可能会写它q{...} if 0;,至少会更清楚一点。
这个 BEGIN 块正在创建 Carp 中函数的自定义版本。它使用该local *__ANON__ = ...行来设置任何匿名子例程的名称,以便更容易跟踪 Carp 堆栈跟踪。BEGIN 块创建包装的 Carp 例程。然后,导入子例程将这些新的包装例程加载到调用者的命名空间中。
最后一段时间似乎正在加载额外的插件模块uni::perl。
同样的事情还没有做,请参阅#3 的答案。(BEGIN创建包装例程,import将它们安装到调用者的空间中)