Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I dynamically get a list of functions or function names from any Perl module?

I would like to dynamically get a list of either function names (as strings) or function references from any arbitrary Perl module available on my system. This would include modules that may or may not have, e.g., a global @EXPORT_OK array in its namespace. Is such a feat possible? How does one pull it off if so?

Edit: From reading perlmod, I see that %Some::Module:: serves as a symbol table for Some::Module. Is this the correct place to be looking? If so, how can I whittle the table down to just the function names in Some::Module?

like image 465
Richard Simões Avatar asked Dec 09 '10 23:12

Richard Simões


2 Answers

You're on the right track. To wittle down the full symbol table to just the subs, something like this can be done (Hat tip "Mastering Perl", ch 8, for main package version of this):

use strict; # need to turn off refs when needed
package X;

sub x {1;};
sub y {1;};
our $y = 1;
our $z = 2;

package main;

foreach my $entry ( keys %X:: ) {
    no strict 'refs';
    if (defined &{"X::$entry"}) {
        print "sub $entry is defined\n" ;
    }
}

# OUTPUT
sub y is defined
sub x is defined
like image 122
DVK Avatar answered Nov 04 '22 03:11

DVK


You may find this simple script handy:

#!/usr/bin/env perl
use strict;
use warnings;    
use Data::Dumper;

# dump of object's symbol table:
foreach my $className (@ARGV)
{
    print "symbols in $className:";

    eval "require $className";
    die "Can't load $className: $@" if $@;

    no strict 'refs';
    print Dumper(\%{"main::${className}::"});
}

But, if you're doing this in production code, I'd use Package::Stash instead:

my @subs_in_foo = Package::Stash->new('Foo')->list_all_symbols('CODE');
like image 42
Ether Avatar answered Nov 04 '22 04:11

Ether