views:

847

answers:

4

How do I list available methods on a given object or package in Perl?

+4  A: 

If you have a package called Foo, this should do it:

no strict 'refs';
for(keys %Foo::) { # All the symbols in Foo's symbol table
  print "$_\n" if defined &{$_}; # check if symbol is method
}
use strict 'refs';

Alternatively, to get a list of all methods:

no strict 'refs';
my @methods = grep { defined &{$_} } keys %Foo::;
use strict 'refs';
Chris Lutz
Should recurse down the @ISA arrays aswell
Beano
Testing this on XML::Simple, Scalar::Util and Exporter shows all methods that are explicitly exported. Recursing down @ISA shouldn't be that hard, though.
Chris Lutz
Of course, you will have a hard time finding autoloaded methods.
innaM
@Manni , and of course, you'll also have a hard time /using/ autoloaded methods.
Kent Fredric
exists instead of defined will show autoloaded methods for which there are forward declarations.
ysth
Why would you have a hard time using autoloaded methods? I bet most people don't even know when they are using them. They call a documented method and the right stuff happens.
brian d foy
Thanks, that's exactly what i was looking for.Unfortunately, i can't depend on Class::Inspector nor moose because i need my one-file script to run a wide variety of systems (solaris 2.6 -> 10, IRIX, HPUX, Linux), so that builtin introspection is very fine.
Benoît
Glad to help. As has been mentioned, it may be prudent for each package to check @Foo::ISA, and then check all those packagaes. You can make a subroutine that you send a package name and it checks that package and all packages in that package's ISA recursively. It shouldn't be too hard.
Chris Lutz
Actually, i'd like to write a method in my base package to list all the available method on a given derived object. like A <- B <- C, $a = new $C; $c->available_methods() -> (A::*, B::*, C::*). I think i'll eventually copy/paste Class::Inspector into my 1-file script.
Benoît
+8  A: 

There are (rather too) many ways to do this in Perl because there are so many ways to do things in Perl. As someone commented, autoloaded methods will always be a bit tricky. However, rather than rolling your own approach I would suggest that you take a look at Class::Inspector on CPAN. That will let you do something like:

my @methods =   Class::Inspector->methods( 'Foo::Class', 'full', 'public' );
Nic Gibson
I've finally included inline Class::Inspector in my one-file script, that's actually the simpler solution. Thanks.
Benoît
Note that Class::Inspector has limitations. It can see defined methods, but does not handle anything in UNIVERSAL.
brian d foy
It's not like the accepted answer handles UNIVERSAL either...
ephemient
+2  A: 

if you have a package that is using Moose its reasonably simple:

print PackageNameHere->meta->dump;

And for more complete data:

use Data::Dumper;
print Dumper( PackageNameHere->meta );

Will get you started. For everything else, theres the methods that appear on ->meta that are documented in Class::MOP::Class

You can do a bit of AdHoc faking of moose goodness for packages without it with:

use Class::MOP::Class;
my $meta = Class::MOP::Class->initialize( PackageNameHere );

and then proceed to use the Class::MOP methods like you would with Moose.

For starters:

 $meta->get_method_map();

use Moose; #, its awesome.

Kent Fredric
initialize will return the metaclass if it's cached, no need to check for it manually, see for example the implementations for all the sugar in Moose.pm
perigrin
Hmm and with further investigation I appear to be both right and wrong. Class::MOP::class_of() will handles instances as well as Class names, while the function that initialize uses (Class::MOP::get_metaclass_by_name()) *only* handles Class names.
perigrin
+2  A: 

In general, you can't do this with a dynamic language like Perl. The package might define some methods that you can find, but it can also make up methods on the fly that don't have definitions until you use them. Additionally, even calling a method (that works) might not define it. That's the sort of things that make dynamic languages nice. :)

What task are you trying to solve?

brian d foy