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

Hi Perl Monks
I posted this on Unix.com but haven't had a bite, so next stop here...

In my code, I know I can write...

if ( defined &test_sub ) { test_sub(); } else { print "Subroutine doesn't exist"; }

This tests the existence of the test_sub subroutine without actually calling it.
If, though, I replace test_sub with a package method...

if ( defined &$TEST->test_sub ) { TEST->test_sub; } else { print "Method doesn't exist"; }
I get
Not a CODE reference at (eval 22)[/opt/perl/5.8.0/lib/perl5db.pl:17] l +ine 2, <STDIN> line 3.

Any suggestions what I'm doing wrong?

Replies are listed 'Best First'.
Re: How to determine if a package method is defined
by almut (Canon) on Sep 30, 2009 at 22:54 UTC

    Not exactly sure whether you meant $TEST or TEST, but maybe you want

    if ( defined &TEST::test_sub ) { # package TEST if ( defined &{"${TEST}::test_sub"} ) { # package in $TEST

    (The One :) difference between defined &{"${TEST}::test_sub"} and $TEST->can("test_sub") is that the latter would consider inheritance, while the former would not — so which one to use depends on what exactly you want...)

      Not really. can checks if a method exists, not if it has been defined.

      sub foo; print( __PACKAGE__->can('foo') ?1:0,"\n"); # 1 print( defined(&foo) ?1:0,"\n"); # 0 print( exists(&foo) ?1:0,"\n"); # 1
      To check if an inherited method is defined, you need
      my $method_ref = __PACKAGE__->can('foo'); print( $method_ref && defined(&$method_ref) ?1:0,"\n");

      That's said, it's quite likely that the OP should have been using exists and that can will do the trick by itself.

        it's quite likely that the OP should have been using exists and that can will do the trick by itself.

        Well, depends on whether this is the desired result...

        #!/usr/bin/perl $TEST = "foo"; if ( $TEST->can("test_sub") ) { $TEST->test_sub; } else { print "Method doesn't exist"; } package foo; sub test_sub; __END__ Undefined subroutine &foo::test_sub called at ./798474.pl line 6.

        And if the method was defined (likely, in real life, if it's there at all), the difference between defined and exists wouldn't matter (which is why I skipped that part and focused on the inheritance aspect).  In other words, I'd say in practical terms the difference between defined and exists is mostly irrelevant (after all, why would people declare bodiless subs in their packages), but if you want to be sure a method can actually be called, then do test whether it's defined...

Re: How to determine if a package method is defined
by Your Mother (Archbishop) on Sep 30, 2009 at 23:16 UTC

    Not quite a direct answer to the question but you can can.

    cow@moo>perl -MCGI -le 'print CGI->can("param") ? "yes" : "no"' yes cow@moo>perl -MCGI -le 'print CGI->can("paramz") ? "yes" : "no"' no

    See UNIVERSAL and search around in here for more on it.

Re: How to determine if a package method is defined
by Bloodnok (Vicar) on Sep 30, 2009 at 22:56 UTC
    If you mean 'how do I test if a class, or any of its ancestors, supports a method?', then can is your friend i.e. in your case, the test would become $TEST->can(q/test_sub/).

    Otherwise, if the question revolves around a sub/method being defined in a specific module, then you were close, but you forgot to consider precedence - if you'd have written defined &{$TEST->test_sub} or defined &{qq/${TEST}::test_sub/}...

    P.S. Thanx for the tip almut - originally forgot the braces in the string

    A user level that continues to overstate my experience :-))
      defined &{$TEST->test_sub}

      This would actually (try to) call the method...

      #!/usr/bin/perl my $TEST = "foo"; if ( defined &{$TEST->test_sub} ) { } __END__ Can't locate object method "test_sub" via package "foo" (perhaps you f +orgot to load "foo"?) at ./798474.pl line 4. --- #!/usr/bin/perl my $TEST = "foo"; if ( defined &{$TEST->test_sub} ) { } package foo; sub test_sub { print "hi\n" } __END__ hi
Re: How to determine if a package method is defined
by jerryhone (Sexton) on Oct 01, 2009 at 07:55 UTC
    Thanks Monks. "can" works a treat! I've never heard of it before, but it's logged for future use now. I could've spent days hunting that down - it's not referenced in my 13 year old 2nd edition O'Reilly Programming Perl, so maybe I need to upgrade! And I can post under my real login today rather than creeping around in the shadowy cloisters as I was forced to last night!