http://qs1969.pair.com?node_id=697710

amir_e_a has asked for the wisdom of the Perl Monks concerning the following question:

What would be the (relatively) best way to list all functions of a package or methods of an object?

The best way i could think of is:

my $instance = new Class::Name; sub print_methods { my ($obj) = @_; my $class = ref $obj; foreach my $name (eval "keys %${class}::") { if ($obj->can($name)) { print "obj can do $name\n"; } } } print_methods($instance);

There must be a better way, but i gave up trying to find the right typeglob-related syntax. The eval "keys %${class}::" can certainly be better. Besides there must be some way to get all symbol table entries for which {CODE} is defined instead of using $var->can(), but yet again, i failed to write something that would compile.

And yes, i understand that it wouldn't find AUTOLOAD's and possibly some other funny stuff - that's why i wrote "the (relatively) best way".

Any help will be appreciated.

Replies are listed 'Best First'.
Re: Listing the functions of a package / methods of an object
by zentara (Archbishop) on Jul 15, 2008 at 16:50 UTC
    I use this often:
    #!/usr/bin/perl use strict; use warnings; #by Abigail of perlmonks # example usage: $0 IO::File my $class = shift or die "need a class\n"; eval "use $class"; die $@ if $@; # First, find all the classes, and the ones it inherits. my %classes = ($class => 1); my @classes = ($class); while (@classes) { my $class = pop @classes; no strict 'refs'; foreach my $class (@{"$class\::ISA"}) { next if $classes {$class} ++; push @classes => $class; } } # Then find the subs in those classes. while (my $class = each %classes) { no strict 'refs'; print "From class '$class':\n"; while (my $entry = each %{"$class\::"}) { print "\t$entry\n" if defined &{"$class\::$entry"}; } } __END__

    I'm not really a human, but I play one on earth CandyGram for Mongo
Re: Listing the functions of a package / methods of an object
by friedo (Prior) on Jul 15, 2008 at 14:44 UTC
    You don't have to use eval to get the keys of the package's symbol table, just do
    my @subs; { no strict 'refs'; my $st = $class . '::'; @subs = keys %$st; }

    Unfortunately, there's no way to differentiate between methods and regular subroutines, and as moritz pointed out, that won't find inherited methods which exist in different packages. Moose's metaclass facilities are really great, but naturally they only work for objects that are built with Moose.

    There is Class::Inspector, which has a reasonably good function to search a class's @ISA tree and get a list of every possible inherited method.

Re: Listing the functions of a package / methods of an object
by stvn (Monsignor) on Jul 15, 2008 at 18:22 UTC

    This will work with any Plain Old Perl Package, no Moose-ness required.

    my @methods = Class::MOP::Class->initialize('Class::Name')->compute_al +l_applicable_methods;
    Each element of @methods will be a HASH ref containing
    • method name
    • the name of the class in which the method lives
    • a Class::MOP::Method instance that contains the CODE ref for the actual method
    As with your version (and pretty much any introspection out there) it will not handle AUTOLOAD (IMO - AUTOLOAD is evil anyway, it shouldn't be used and any modules that use it should be treated with suspicion). It will also properly ignore imported functions as well, like if you were to import Scalar::Util::blessed into your package, Class::MOP::Class would properly ignore it since it is not a method.

    -stvn
Re: Listing the functions of a package / methods of an object
by moritz (Cardinal) on Jul 15, 2008 at 14:00 UTC
    Use Moose or another OO framework that allows easy introspection.

    Without having checked, I think your code will fail to list method in superclasses of $object

    (And shouldn't $result be really $object?)

      > Use Moose or another OO framework that allows easy introspection.

      Hmm ... but nothing for the old-fashioned plain blessed packages?..

      > Without having checked, I think your code will fail to list method in superclasses of $object

      You're right :(

      > And shouldn't $result be really <c>$object?

      Of course it should :)

        Class::MOP (which is the foundation of Moose) works well with the "old-fashioned" plain blessed hashref packages and has the functionality you are looking for. It is provided via Class::MOP::Class method_map.
        Hmm ... but nothing for the old-fashioned plain blessed packages?..

        I think you can do better (for example recurse into the classes @ISA, and filter out methods beginning with an underscore (which are private by convention), DESTROY etc.), but there are conceptual limits.

        Perl doesn't have different declarations for subs and methods, so it's impossible to distinguish these two automatically.

        Maybe there are better solutions to your problem. For example the thread Runtime introspection: What good is it? discusses (among a variety of other things) possible alternatives to to introspection.

Re: Listing the functions of a package / methods of an object
by clinton (Priest) on Jul 15, 2008 at 14:43 UTC

    You don't specify, but if what you're after is a debugging tool, rather than something that you want to integrate into other code, then use the Perl debugger:

    perl -d -MDBI -e 5 > $d = DBI->new(); > m $d # or just "m DBI"

    This returns: