gpt4 book ai didi

perl - 使用 "isa"方法的最佳方法?

转载 作者:行者123 更新时间:2023-12-03 21:24:40 36 4
gpt4 key购买 nike

可靠地使用“isa()”的“最佳”方式是什么?换句话说,它可以在 上正常工作任何 值(value),而不仅仅是一个对象。

“最好”是指没有未处理的极端情况以及没有潜在的性能问题,所以这不是一个主观问题。

This question提到了两种看起来可靠的方法(请注意,不应使用旧样式 UNIVERSAL::isa(),原因在该问题的答案中有详细记录):

eval { $x->isa("Class") }
#and check $@ in case $x was not an object, in case $x was not an object

use Scalar::Util 'blessed';
blessed $x && $x ->isa($class);

第一个使用 eval ,第二个使用 B:: (至少对于非 XS 风格的 Scalar::Util)。

如果 $x,第一个似乎无法正常工作是一个包含类名的标量,如下所示,所以我倾向于#2(使用 blessed ),除非 somoene 表明有充分的理由不这样做。
$ perl5.8 -e '{use IO::Handle;$x="IO::Handle";
eval {$is = $x->isa("IO::Handle")}; print "$is:$@\n";}'
1:

是否有任何客观原因选择这两种方法之一(或我不知道的第三种),例如性能,不处理某些特殊情况等......?

最佳答案

Scalar::Util 实现绝对更好。它避免了 eval {} 的开销,这总是导致设置附加变量。

perl -we'$@=q[foo]; eval {}; print $@'
Scalar::Util 实现更容易阅读(它不会因为代码未知的原因而死)。如果 eval 也失败了,我相信会发生什么是你在树中向后走到 eval 之前的状态——这就是重置状态的实现方式。这会带来额外的失败开销。

基准

根本不是对象
          Rate eval   su
eval 256410/s -- -88%
su 2222222/s 767% --

对象通过 isa 检查
          Rate   su eval
su 1030928/s -- -16%
eval 1234568/s 20% --

对象未通过 isa 检查
         Rate   su eval
su 826446/s -- -9%
eval 909091/s 10% --

测试代码:
use strict;
use warnings;
use Benchmark;
use Scalar::Util;

package Foo;

Benchmark::cmpthese(
1_000_000
, {
eval => sub{ eval{ $a->isa(__PACKAGE__) } }
, su => sub { Scalar::Util::blessed $a && $a->isa(__PACKAGE__) }
}
);

package Bar;

$a = bless {};

Benchmark::cmpthese(
1_000_000
, {
eval => sub{ eval{ $a->isa(__PACKAGE__)} }
, su => sub { Scalar::Util::blessed $a && $a->isa(__PACKAGE__) }
}
);

package Baz;

$a = bless {};

Benchmark::cmpthese(
1_000_000
, {
eval => sub{ eval{ $a->isa('duck')} }
, su => sub { Scalar::Util::blessed $a && $a->isa( 'duck' ) }
}
);

我使用了这是为 i486-linux-gnu-thread-multi 和 Scalar::Util1.21 构建的 perl、v5.10.1 (*)

关于perl - 使用 "isa"方法的最佳方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2977775/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com