Scalar::Util::Ref

instanceof演算子を実装してみた。
Scalar::Util::Ref

#!perl
use strict;
use IO::File;
use instanceof;
my $x = IO::File->new();
if($x << 'IO::Handle'){
    print "$x is an instance of 'IO::Handle'\n";
}
__END__

Scalar::Util::blessed()&isa()と比べると,Perl 5.8.5 on Linuxでこんな感じになる。

For Foo=HASH(0x8246528)
                Rate scalar_util  instanceof
scalar_util  55138/s          --        -60%
instanceof  137845/s        150%          --

For Foo::X::X::X=HASH(0x835811c)
               Rate scalar_util  instanceof
scalar_util 45948/s          --        -53%
instanceof  98248/s        114%          --

For Unrelated=HASH(0x835cf5c)
                Rate scalar_util  instanceof
scalar_util  49320/s          --        -55%
instanceof  109226/s        121%          --

For undef
                Rate scalar_util  instanceof
scalar_util 122879/s          --        -62%
instanceof  319956/s        160%          --

このようにほぼ常に2倍ほど速いので,isa()を大量に呼び出す場合は有効かもしれない。更に,5.8.xでは5.10.0の機能を効率の悪いやり方でエミュレートしているので,最新のPerlではもう少し高速になるはず。

ベンチマークコード:

#!perl -w
use strict;
use Benchmark qw(:all);
use Scalar::Util qw(blessed);

BEGIN{
	package Base;
	sub new{
		bless {} => shift;
	}
	package Foo;
	our @ISA = qw(Base);
	package Foo::X;
	our @ISA = qw(Foo);
	package Foo::X::X;
	our @ISA = qw(Foo::X);
	package Foo::X::X::X;
	our @ISA = qw(Foo::X::X);
	package Unrelated;
	our @ISA = qw(Base);
}
foreach my $x (Foo->new, Foo::X::X::X->new, Unrelated->new, undef){
	print 'For ';
	if(defined $x){
		print $x;
	}
	else{
		print 'undef';
	}
	print "\n";
	my $i = 0;
	cmpthese -1 => {
		'scalar_util' => sub{
			for(1 .. 10){
				$i++ if blessed($x) && $x->isa('Foo');
			}
		},
		'instanceof' => sub{
			use instanceof;
			for(1 .. 10){
				$i++ if $x << 'Foo';
			}
		},
	};

	print "\n";
}
__END__