だるろぐ

だるいぶろぐです

rubyの obj.methods がperlにも欲しい

以前 メソッドの一覧を取得する - だるろぐ とかやったんだけど、ruby

p obj.methods

みたいにしたい。ので

package Foo;
use strict;
use warnings;

sub new { bless {}, shift }
sub hoge {}
sub foo {}

my $var_my = 1;
our $var_our = 3;

package UNIVERSAL::methods;
use strict;
use warnings;

sub UNIVERSAL::methods {
    my $self = shift;

    my $class = ref $self;
    my @methods;

    no strict "refs";

    while (my ($key, $value) = each %{"$class\::"}) {
        not defined ${"$class\::$key"} and push @methods, $key;
    }

    \@methods;
}

package main;
use strict;
use warnings;
use URI;
use Data::Dumper;
sub p {warn Dumper @_;my @c = caller;}

my $f = Foo->new;
p $f->methods;

実行すると

% perl main.pl
$VAR1 = [
          'DESTROY',
          'AUTOLOAD',
          'BEGIN',
          'methods',
          'new',
          'foo',
          'hoge'
        ];

と一見よさそうなんだけど

my $u = URI->new;
p $u->methods;

を試すと

$VAR1 = [
          'rel',
          'path_query',
          'AUTOLOAD',
          '_check_path',
          'methods',
          'BEGIN',
          '_init',
          'uri_unescape',
          'path',
          'path_segments',
          'DESTROY',
          '_no_scheme_ok',
          'abs',
          'ISA',
          'authority',
          '_split_segment'
        ];

と残念に。まぁ 変数 or 関数 の区別が手抜きなのでしょうがない。

物凄い勢いで追記(Fri Jun 11 00:14:24 JST 2010)

こうすりゃいいか?

    while (my ($key, $value) = each %{"$class\::"}) {
        *{${"$class\::"}{$key}}{CODE} and push @methods, $key;
    }
$VAR1 = [
          'new',
          'foo',
          'hoge'
        ];
$VAR1 = [
          'rel',
          'path_query',
          '_check_path',
          'uri_unescape',
          'path',
          'path_segments',
          '_no_scheme_ok',
          'abs',
          'authority',
          '_split_segment'
        ];

駄目ですね。

更に追記

ボスに相談したら
「canでええやん」
確かに!シンボルテーブル覗いて得られたやつの全部にcanすればええやん!
ありがとうございました。