[Melbourne-pm] New perl5i feature, $obj->mo->methods

Michael G Schwern schwern at pobox.com
Wed Jan 26 20:56:16 PST 2011


At the pub after the last meeting, per5li came up.  I think Myf wanted to kill
smart quotes with a regex, which got into the scary \N{...} syntax.  perl5i
came up because it turns on utf8 by default, so you can write:

        use perl5i::2;

        my $string = q[“I know better than you”, said the word processor.];
	$string =~ s{[“”]}{"}g;
        say $string;

I was showing off the introspection features in perl5i (what's an object's
class, its parents, a complete inheritance walk...) and Myf asked about
getting the methods of an object.  You can do that in Perl, but normally this
involves scary symbol table and glob stuff.  No more!  Myf, Jacinta and I
hacked out a quick implementation at the pub, and I cleaned it up later and
now it's released in v2.5.0.

So, thank you Melbourne.pm for two new perl5i features!  The first gets the
symbol table for a class, which is necessary to do method introspection.

    my $table = $obj->mo->symbol_table;

Amazingly, it's four lines.

    sub symbol_table {
        my $self = shift;
        my $class = $self->class;

        no strict 'refs';
        return \%{$class.'::'};
    }

It's really easy, but it's something that I always forget and it's very poorly
documented in the Perl docs.  The symbol table is what holds all global
variables and functions for each class.

And then a method to ask any object what its methods are.

    my @methods = $obj->mo->methods;

By default, that excludes stuff from UNIVERSAL, but you can turn that back on.
 There's also an option to show just the methods defined in that class.
Here's the version without the options.

    for my $class ($self->linear_isa) {
        next if $class eq "UNIVERSAL";

        my $sym_table = $class->mc->symbol_table;
        for my $name (keys %$sym_table) {
            next unless *{$sym_table->{$name}}{CODE};
            $all_methods{$name} = $class;
        }
    }

    return wantarray ? keys %all_methods : [keys %all_methods];

The only scary thing in there is *{$sym_table->{$name}}{CODE}.  That's looking
in the symbol table for the typeglob associated with a thing.  A typeglob can
be thought of as a hash with a really bad interface.  It has slots to hold
code refs, scalar refs, array refs and hash refs.  CODE, SCALAR, ARRAY and
HASH.  You get at them with *glob{THING}.  So *{$sym_table->{$name}}{CODE}
gets the glob for whatever is in $name and checks if there's a code ref there.
 That's how you check if a method is defined in a class.

And the best part is this: you don't need to know any of that!  You can just
use it.  It's in v2.5.0 which I shoved out here at LCA.

My talk from OSDC on perl5i is up if you want to know more.
http://blip.tv/file/4447749


-- 
'All anyone gets in a mirror is themselves,' she said. 'But what you
gets in a good gumbo is everything.'
    -- "Witches Abroad" by Terry Prachett



More information about the Melbourne-pm mailing list