tags:

views:

379

answers:

4

How can I find which object type I am dealing with in Perl? I tried using perl -d to enter the debugger, but I'm not sure what to do then. Likewise I'd like a way to easily see which methods are available for each object, how can that be done?

+1  A: 
Hamish Grubijan
+6  A: 

The blessed function from Scalar::Util will tell you the package name of any blessed reference (an object.)

To find out what methods are available, consult the documentation for that package. Alternatively, you can use something like Class::MOP::Class to instantiate a metaclass and get introspective information about the methods it contains.

friedo
+4  A: 

The standard way for telling what type of object you have is either ref or Scalar::Util::blessed. If you know the object is blessed, then they return the same information.

my $class1 = blessed( $obj );
my $class2 = ref $obj;

But ref will also return 'HASH' for unblessed hashes, while blessed refuses to play that game.

As for a list of methods, for the blessed pointer style of perl object, it's easy enough to code one up yourself. The code below works fairly well for me. It returns the names of functions (those taking the "CODE slot" of the given name) mapped to the package which defines them.

sub class_methods { 
    use Class::ISA;
    my $obj = shift;
    return unless ref( $obj );
    my %meth_names;
    foreach my $anc ( Class::ISA::self_and_super_path( ref $obj ), 'UNIVERSAL' ) {
        my $stash = \%{"$anc\::"};
        my @funcs 
            = grep { m/^[_\p{Alpha}]/                # begins with _ or alpha
                   && !exists $meth_names{$_}        # no clobbering
                   &&  defined *{$stash->{$_}}{CODE} # has a filled CODE slot
                   } keys %$stash
            ;
        # assign to the "hash slice", keyed by all the entries in @funcs
        # the value of $anc repeated as many times as elements in @funcs.
        @meth_names{@funcs} = ( $anc ) x @funcs;
    }
    return %meth_names;
}
  • This will work for reasonably complex objects as well, but if the owning package contains a lot of generated code, it's not going to be that helpful to know which package the generators stuck the code pointer in. It's going to mean more to find what package generated the code.

  • This being the case, you might get the code out of running your code, including Data::Dumper and setting $Data::Dumper::Deparse to 1, like so: ( local $Data::Dumper::Deparse = 1;) and then dumping the code pointer, like so: say Dumper( $code_ref );

  • It WON'T work for valid methods that have yet to be created by any AUTOLOAD methods. If you see those in the list, the object might do more, but what all it does, you don't know.

  • The "base class" UNIVERSAL is included, because that class contains behavior usable by the object.

Good luck.

Axeman
A: 

Just for completeness, here's a very short intro to the debugger.

perl -d your_program

starts it under the bugger. You'll get control at the first executable line (use statements and the like have already executed at this point).

's' will step to the next line. Once you've entered an 's', you can simply press return to repeat it. 's' will step down into functions/subroutines/methods. Either keep stepping till you return or enter the 'r' command to execute the rest of the function and return to right after the call.

If you want to step 'over' subroutines - that is, execute them and return without having to step in and return, use 'n. The carriage return after the first 'n' also keeps doing 'n' for you.

If you know the line where you want to stop, use the 'b' command - b linenumber - to set a breakpoint, then 'c' to continue till you reach it. Note that every time you 'c' and come back to the breakpoint you will stop again. Use 'B linenumber' to turn the breakpoint back off.

So let's assume you've gotten to something like this:

my $obj = complex_function_returning_unknown_thing;

The debugger's just shown you this line, which says "I have not executed this yet, but it is what I will do next." Enter 'n' to execute the subroutine, then use the 'x' command to look at the object: 'x $obj'. If it's big, you can say '|x $obj' which runs the output through a pager. To see what methods the object has, use 'm $obj'.

There's a lot more to the debugger, but you can indeed use it for this kind of thing - you need to simply see the type of an object you're getting from some code and find out what methods the object you got has.

It may be more useful to 'x' the object, and then go look at the source of the class the object's been blessed into to find out what you should do as opposed to what you can do. The 'x' command is pretty much 'print ref($obj)' crossed with Data::Dumper anyway.

Joe McMahon