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

Lets say I have an object I've declared as follows:

use Some::Module; my $obj = Some::Module->new();

I now want to get a list of all the functions that $obj can execute. (without reading the perldoc for the module obviously.)

-Andrew.


Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com

Replies are listed 'Best First'.
Re: Reflecting on Object
by merlyn (Sage) on Jul 21, 2005 at 00:42 UTC
Re: Reflecting on Object
by halley (Prior) on Jul 20, 2005 at 23:56 UTC
    Since Perl can adjust its symbol tables on the fly, even WHILE making a call to a routine, this is akin to the unsolvable "halting problem."

    You can scan the source code for the package file. You can scan the current state of the symbol table. You can even look at the source code to any AUTOLOAD and DYNALOAD libraries to see what they might hint at adding on the fly. [Update I forgot to mention that you'll then have to walk the @ISA tree for all inherited packages, each such package with the same problems.] And you'd still have a potentially incomplete list.

    --
    [ e d @ h a l l e y . c c ]

      OK, ignoring that, how do I scan the current symbol table for functions that will work with $obj?

      -Andrew.


      Andrew Tomazos  |  andrew@tomazos.com  |  www.tomazos.com
      Actually, this isn't equivalent to the halting problem. If you can guarentee that there are no other threads executing, it's possible to guarentee that the code you write to discover the available methods doesn't modify $obj in any way, and so you can know what methods are available right now. The problem is that that information is only good until you execute some code that might change $obj. It's also impossible to compensate for AUTOLOAD.
        You break your own argument here. From the caller's point of view, a call appears atomic, but thanks to AUTOLOAD, the call itself is able to modify the world, even before the eventually-installed method is entered. You can stop time just before the call, and still not prove what methods are available. QED.

        And words are important: I said 'akin,' not 'equivalent.' There are differences. However, they're both in a group of unprovable-because-the-domain-can-change problems.

        --
        [ e d @ h a l l e y . c c ]

Re: Reflecting on Object
by tlm (Prior) on Jul 21, 2005 at 00:23 UTC

    As a first approximation (with all the caveats already mentioned by halley):

    { no strict 'refs'; @my_subs = grep exists &{ 'Some::Module::' . $_ }, keys %Some::Modul +e::; }
    This only tells you the subs in Some::Module's symbol table at the time. For one thing it does not differentiate between instance methods and class methods. Neither does it differentiate betweeen "methods" (i.e. functions that are expected to be called through a -> notation) and regular functions. In fact, if Some::Module imported some random function (e.g. croak or floor), it will be listed in @my_subs. It also doesn't show subs stored in lexicals.

    Try it with a module you know (or think you know) and see what you get.

    Update: Also, the above does not take into account inheritance. You'd need to adapt it to travel up @ISA's to get inherited methods.

    the lowliest monk

Re: Reflecting on Object
by adrianh (Chancellor) on Jul 21, 2005 at 11:08 UTC
    I now want to get a list of all the functions that $obj can execute

    Class::Can does exactly this.

Re: Reflecting on Object
by Anonymous Monk on Jul 21, 2005 at 14:23 UTC
    Well, you can walk the stash of the class the object belongs to, and the stashes of the classes this class directly and indirectly inherits, and the stash of UNIVERSAL. It will give you a bunch of subroutine names.

    But it won't be easy to determine which ones are supposed to be methods (and hence callable from the outside), and which ones are subroutines not meant as methods.

    I'd skim the PODs!