どのように動かないPerlライブラリのメソッドリストを動力学的に得ることができますか?どのように私はダイナミックに(ムースでない)Perlライブラリのメソッドのリストを取得できますか?
私は、委任を使用してMooseクラスに非Mooseクラスをラップしようとしています。現在、私は委任しているメソッドのリストをハードコーディングしています。大したことではありませんが、もっとエレガントな方法があるのだろうかと思っていました。
どのように動かないPerlライブラリのメソッドリストを動力学的に得ることができますか?どのように私はダイナミックに(ムースでない)Perlライブラリのメソッドのリストを取得できますか?
私は、委任を使用してMooseクラスに非Mooseクラスをラップしようとしています。現在、私は委任しているメソッドのリストをハードコーディングしています。大したことではありませんが、もっとエレガントな方法があるのだろうかと思っていました。
不可能です。サブが方法であるかどうかを区別する方法はありません。代わりにサブシステムの一覧を表示することができたら、
grep exists(&{ 'Foo::Bar::'.$_ }), keys %Foo::Bar::
もちろん、継承ツリーはスキャンされません。あなたがそれをしたい場合は、厳密に言及した池上として、潜水艦と方法を区別することは不可能でいえば、
mro::get_linear_isa('Foo::Bar')
まあを使用してスキャンするパッケージのリストを取得することができます。
しかし、あなたが創造的得ればもちろん偽陽性と偽陰性の両方が可能であるが、あなたは常に 、ちょっと例大半のメソッドからサブを区別みかんするPadWalker'speek_sub
とclosed_over
を使用することができます。
use strict;
use warnings;
use PadWalker;
my $self;
sub test_sub
{
my $x = shift;
print $self;
}
sub test_method
{
my $self = shift;
}
sub is_method
{
my $coderef = shift;
my $all = PadWalker::peek_sub($coderef);
my $closed = PadWalker::closed_over($coderef);
for my $k (qw($self $me $class)) {
return 1 if $all->{$k} && !$closed->{$k};
}
return 0;
}
print "test_sub: ", is_method(\&test_sub) ?
"is a method\n" : "is a sub\n";
print "test_method: ", is_method(\&test_method) ?
"is a method\n" : "is a sub\n";
コードリーダーを取得することは、読者の練習として残されています。
ikegamiの答えの1つは、Package::Stash
モジュールを使用することです。そのlist_all_symbols
メソッドは、指定されたパッケージのすべてのサブ名を返します。次に例を示します。
perl -MPackage::Stash -E "say for Package::Stash->new('Package::Stash')->list_all_symbols('CODE')"
私は-Eについて知らなかった。クール。 –
すでにMooseを使用している場合は、Class :: MOPを使用できます。私はクラス:: MOPは最もクリーンな方法だと思うし、また、すべてのメソッド/関数を継承からフェッチすることができます。しかし、他の人が言ったように、方法と機能を区別することはできません。
use Class::MOP;
use Test::More;
my $class = Class::MOP::Class->initialize('Test::More');
my @methods = $class->get_method_list(); # Only Methods in this Class
my @all_methods = $class->get_all_methods(); # Include all inherited methods
printf "%d functions in Test::More\n", scalar @methods;
printf "%d functions including inheritance\n", scalar @all_methods;
print "methods: @methods\n\n";
print "all methods: ", join(' ', map({ $_->fully_qualified_name } @all_methods)), "\n";
これらの印刷物は、このようsomethink:
も39 functions in Test::More
49 functions including inheritance
methods: subtest _whoa cmp_ok isa_ok use_ok isnt _format_stack like _eq_array plan _eval fail _carp done_testing _type diag _is_module_name import_extra eq_array require_ok BAIL_OUT _dne is ok _eq_hash explain todo todo_skip unlike new_ok eq_set pass can_ok eq_hash is_deeply note _equal_nonrefs _deep_check skip
all methods: Exporter::export_fail Test::More::_whoa Test::More::subtest Exporter::export_tags Test::More::cmp_ok Test::More::use_ok Test::More::isa_ok Test::More::_format_stack Test::More::isnt Test::More::like Test::More::_eq_array Test::More::plan Exporter::export Test::More::_eval Test::More::_carp Test::More::fail Test::More::done_testing Test::More::_type Test::More::diag Test::Builder::Module::_strip_imports Test::More::_is_module_name Test::More::import_extra Exporter::as_heavy Test::More::eq_array Test::More::require_ok Exporter::export_to_level Test::More::BAIL_OUT Test::More::_dne Test::More::is Test::More::ok Exporter::export_ok_tags Test::More::explain Test::More::_eq_hash Test::More::todo_skip Test::More::todo Test::More::new_ok Test::More::unlike Test::More::pass Test::More::eq_set Test::More::can_ok Test::More::eq_hash Test::More::is_deeply Test::More::note Test::Builder::Module::import Test::More::_equal_nonrefs Test::More::skip Test::More::_deep_check Exporter::require_version Test::Builder::Module::builder
、AUTOLOAD動的またはシンボルテーブルに – mirod
感謝を表示しない場合があることを、メソッドを作成することができます!私はおそらくこれで逃げることができます。私はおそらくそれをハードコード化したままにします。私はそれがいつも変わることはないと思っています。それではなぜCPUサイクルを費やすのですか? –
@mirod、AUTOLOADについては言及していませんでした。なぜなら、AUTOLOADが処理する名前を知ることは不可能だからです。 – ikegami