在我的
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’标志,但不明白在这种情况下正在做什么..使用mro是一些“黑魔法”可能是一个常见的perl用户不需要知道……;)
本地* __ 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? }; } }
最后 – 一些更清晰的事情.重写导入,这将在使用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 ); } } }
最后一次做什么?
加上问题:
>为什么两次做同样的事情?一旦进入BEGIN区块并进入一次? (导入是用于“使用” – 但为什么在“BEGIN”块中也做同样的事情呢?
因为这个问题有更多部分,请在给出答案时引用相关部分.
谢谢大家.
解决方法
>直接设置警告位有点快,并且具有更可预测的行为(您可以看到应该发生的所有事情),但显然更难以使用和维护.可能是uni :: perl尝试加载的警告集更容易通过位掩码完成. > m {使用严格;使用警告;} x;在void上下文中只是一个正则表达式.如果启用了警告,它将引发关于上下文的错误或者没有设置$_.我不确定为什么要这样做,可能是为了安抚一些寻找“使用警告;使用严格”这一行的代码度量系统.如果为0,我可能会写q {…};至少有点清楚. >这个BEGIN块正在Carp中创建自定义版本的函数.它使用本地* __ ANON__ = …行来设置任何匿名子程序的名称,以便更容易遵循Carp堆栈跟踪. BEGIN块创建包装的Carp例程.然后,import子例程将这些新的包装例程加载到调用者的命名空间中. >最后一次似乎正在为uni :: perl加载额外的插件模块. >同样的事情没有完成,请参阅#3的答案. (BEGIN创建包装例程,导入将它们安装到调用者的空间)