我遇到了这段代码,但我不明白.
$type->isa('UNIVERSAL')
or eval "require $type"
or croak $@;
Run Code Online (Sandbox Code Playgroud)
我已经提到了perldoc,我知道子程序isa()正在检查是否$type已经祝福包装UNIVERSAL.但实际上,所有Perl类都是子类UNIVERSAL,对吧?
我对这两个or术语感到困惑.他们的意思是什么?
or旋律Perl\xe2\x80\x99sor运算符的工作方式与此类似||,但优先级非常低,即 \xe2\x80\x9ctightly\xe2\x80\x9d 它如何绑定到周围的代码。Perl 中的逻辑或短路,即一旦操作数计算为真,计算就会停止。
Perl 中的一个常见习惯用法是使用短路来进行流控制,通常与错误处理相关,如下所示
\n\nopen my $fh, "<", $path or die "$0: open: $!";\nRun Code Online (Sandbox Code Playgroud)\n\n成功后,open返回真值。or当至少一个操作数为 true 时,结果为true,因此在成功时open,perl 不会成功,die因为右侧操作数 toor未求值。
运营商链or可以任意延伸。这对于指定默认值很有用。在简单的情况下,看起来像
my $name = shift or "Bruce";\nRun Code Online (Sandbox Code Playgroud)\n\n如果您有多个后备案例,请将它们按照您想要尝试的顺序排列。
\n\nmy $name = shift or given_name $family_name or "Bruce";\nRun Code Online (Sandbox Code Playgroud)\n\n第一个成功的案件获胜。
\n\n代码
\n\n$type->isa(\'UNIVERSAL\')\n or eval "require $type"\n or croak $@;\nRun Code Online (Sandbox Code Playgroud)\n\n就是这样一个链条。评估按以下顺序进行:
\n\n$type->isa(\'UNIVERSAL\')eval "require $type"croak $@如果$type是已存在的包的名称,则忽略步骤 2 和 3。
到达步骤 2 意味着$type尚未加载,因此现在代码尝试require加载。如果require成功,则忽略步骤 3。
到达步骤 3 意味着该包不存在并且无法加载。在这种情况下,croak输出失败的原因并退出程序。
当作为方法调用时,isa具有三种形式:
\n\n\n\n
\n- \n
$obj->isa( TYPE )- \n
CLASS->isa( TYPE )- \n
eval { VAL->isa( TYPE ) }
第三个是通用的包罗万象,与这里无关。第一个是你在问题中所描述的。
\n\n第二个记录为
\n\n\n\n\n当用作类方法 (
\nCLASS->isa( TYPE ))(有时称为静态方法)时,isa如果CLASS继承(或其本身)包TYPE的名称或继承自包TYPE ,则返回 true 。
来自 SOAP::WSDL::XSD::TypeLib::ComplexType 的or链之前的行是::_factory
my $type = $CLASSES_OF{ $class }->{ $name }\n or croak "No class given for $name";\nRun Code Online (Sandbox Code Playgroud)\n\n这里, 的值$type是一个字符串,因此isa检查名为的类是否$type继承自 UNIVERSAL。正如您在问题中指出的,所有类都继承自 UNIVERSAL。
那么\xe2\x80\x99s 发生了什么?如果isa失败,代码将调用require,因此检查的目的isa必须是确定是否已加载给定的类。
请记住,Perl 类和 Perl 包密切相关。为了使类存在,必须存在同名的包。非破坏性地检测包是否存在是很棘手的。直接探测藏匿处%Foo::Bar::Baz::Quux::会自动复活。Perl 分层存储存储,因此您\xe2\x80\x99d 必须像下面这样进行探索
sub package_exists {\n my($pkg) = @_;\n $pkg =~ s/::$//;\n my @parts = split /::/, $pkg;\n\n my $stash = $main::{"main::"};\n while (@parts) {\n my $subpkg = shift(@parts) . "::";\n return unless exists $stash->{$subpkg};\n $stash = $stash->{$subpkg};\n }\n\n $stash;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n成功修改名为%INCrequire的特殊哈希。我\xe2\x80\x99m 不确定为什么代码不\xe2\x80\x99t 检查。也许某些类型是在 require 机制之外加载的,或者作者可能对这个令人愉快的小技巧感到满意。%INC
sv_derived_from考虑实现 的来源isa。
bool\nPerl_sv_derived_from_pvn(pTHX_ SV *sv,\n const char *const name, const STRLEN len,\n U32 flags)\n{\n dVAR;\n HV *stash;\n\n PERL_ARGS_ASSERT_SV_DERIVED_FROM_PVN;\n\n SvGETMAGIC(sv);\n\n if (SvROK(sv)) {\n const char *type;\n sv = SvRV(sv);\n type = sv_reftype(sv,0);\n if (type && strEQ(type,name))\n return TRUE;\n stash = SvOBJECT(sv) ? SvSTASH(sv) : NULL;\n }\n else {\n stash = gv_stashsv(sv, 0);\n if (!stash)\n stash = gv_stashpvs("UNIVERSAL", 0);\n }\n\n return stash ? isa_lookup(stash, name, len, flags) : FALSE;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n请记住,我们正在调用此代码
\n\n"SomeClass"->isa("UNIVERSAL")\nRun Code Online (Sandbox Code Playgroud)\n\nsosv包含字符串"SomeClass". SvROK检查是否sv是引用,而字符串则不是,所以我们总是在else分支中。
最后, 的值stash将始终为非NULL: 指向包的符号表(如果已加载)或 UNIVERSAL 否则。对于已加载的包,查找成功,否则查找失败。自己尝试一下:
$ perl -le \'print "strict"->isa("UNIVERSAL") ? "已加载" : "未加载"\'\n未加载\n\n$ perl -Mstrict -le \'print "strict"->isa("UNIVERSAL") ? "已加载" : "未加载"\'\n已加载\n