RubyのMethod#source_locationをPerlで

[追記]Cside先生がUNIVERSAL::source_location_forとしてリリースしておりますのでcpanmでご利用ください![/追記]

asakusa.rbでsource_locationというメソッドを教えてもらいました。
それによれば、Rubyのメソッドオブジェクト(UnbountMethod, Method, Procなど)にはsource_locationというメソッドがあり、そのメソッドが定義されたファイル名と行番号を取得することができます。これはクラス階層が複雑なときにデバッグに役立ちそうです。

Perlでも標準ライブラリに含まれるBモジュールを使って同様のことができるのでやってみました。

Ruby版:

#!/usr/bin/env ruby2
require 'fileutils';

p FileUtils.method(:pwd).source_location;
__END__
# result:
["/usr/local/lib/ruby/2.0.0/fileutils.rb", 180]

Perl版:

#!/usr/bin/env perl
use strict;
use warnings;

use B ();

sub UNIVERSAL::source_location_for {
    my($self, $method) = @_;
    my $entity = $self->can($method) or return;
    my $gv     = B::svref_2object($entity)->GV;
    return($gv->FILE, $gv->LINE);
}

use File::Spec;
use Data::Dumper;
print Dumper [ File::Spec->source_location_for('canonpath') ];
__END__
# result:
$VAR1 = [
          '/Users/gfx/perl5/perlbrew/perls/perl-5.14.2/lib/5.14.2/darwin-2level/File/Spec/Unix.pm',
          71
        ];

生の構造体を直接触る感じがPerlらしくていいですね!