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

hey:

if i have a subroutine like:

sub mysub { $obj=shift; $obj->prant('hello world'); }
and $obj->prant doesnt exist, say its a typo,
it should actually be print
how can i detect that?

Replies are listed 'Best First'.
Re: detecting improperly called subroutines
by Ovid (Cardinal) on Apr 15, 2002 at 23:04 UTC

    Ah, the joys of OO programming :)

    Detecting a non-existant method depends upon what you're trying to do. If you mean, "how do I detect this at compile time", you're pretty much out of luck. Methods aren't bound to objects until run-time since, due to polymorphism, Perl has no way of knowing what sort of object you have, thus it can't know at compile time what method is going to be called.

    Thus, you must rely on this method call being trapped at run-time. One way is to simply let Perl try and call the method and have it die. Then, you can read the useful method on the command line and take appropriate action :). If you don't want it to die, you'll have to create an AUTOLOAD method to trap the call and do as you will. One thing you could do is use String::Approx, walk the symbol table and dump a list of method names that prant might be.

    Barring this, you'll just have to watch your typing and use strict.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: detecting improperly called subroutines
by seattlejohn (Deacon) on Apr 15, 2002 at 23:02 UTC
    You can't detect it at compile-time, because Perl doesn't know at that point what the object's class might be and therefore can't determine whether the method call is appropriate or not.

    If you try to call the misspelled method at runtime, you'll get a "can't locate object method..." error. You can trap those errors if you wish by defining an AUTOLOAD subroutine in your class; AUTOLOAD gets called when no other method in the class (or its ancestors) matches.

Re: detecting improperly called subroutines
by chip (Curate) on Apr 15, 2002 at 23:17 UTC
    Misspelled methods can't be detected by Perl's parser--yet. But eventually they will be ... which is why the my Dog $spot syntax will be helpful.

        -- Chip Salzenberg, Free-Floating Agent of Chaos

Re: detecting improperly called subroutines
by impossiblerobot (Deacon) on Apr 15, 2002 at 23:10 UTC
    This reminded me of davorg's Symbol::Approx module, which tries to guess which subroutine you really meant when you mispell (and execute it). :-)

    Of course, you wouldn't want to really use Symbol::Approx in your program, but it is an interesting use of AUTOLOAD.

    Update: Ack! Ovid beat me to to it. :-)

    Impossible Robot
Re: detecting improperly called subroutines
by hossman (Prior) on Apr 15, 2002 at 23:26 UTC
    I think i may have read this question in a more generalized way then the orriginal poster was looking for, I started thinking:

    How can you confirm that an object impliments a given method?

    Which seems really usefull to me in a language without strict typing, or interfaces. Developers can provide APIs in which they say "you can pass me ny object of any class, as long as it impliments the following methods..." and the API can do "friendly" sanity checking of the objects to make sure they impliment all the neccessary methods prior to doing any processing, and generate a "friendly" error and return -- instead of just letting the Interpreter spit out an error msg and keep on processing.

    But i honestly can't think of anyway straightforward way to do a check like this in perl. Looking in the Symbol table seems like a good approach but it doesn't take into account subclassing, so we'd need to "walk the symbol table" .. but i'm affraid my typeglob / symbol table knowledge doesn't extend to dealing with superclass relationships.

    So i propose to extend the orriginal question be extended. Given a package name (as returned by the ref method) what's the best way to determing if "foo" is a valid method name for that package ?

      my $object = Foo->new; if ( $object->can( $some_method ) ) { # it's good } else { # it's bad }

      Cheers,
      Ovid

      Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.