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

I'm trying to figure out the behavior of this, I think it's a bug but would like some confirmation, and whether it's in the latest version or already known. Instead of calling 'can' it calls main() recursively:
#!/usr/bin/perl use strict; use warnings; my $i = 0; main(); sub main { exit if $i++ > 10; print "Calling foo()\n"; foo(); } sub foo { print "foo()\n"; my $fn = main->can("bar") or return; print "We can bar\n"; $fn->(); } __END__
Output:
Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo() Calling foo() foo()

Replies are listed 'Best First'.
Re: Class->can() bug or user error
by chromatic (Archbishop) on Jul 15, 2011 at 19:21 UTC

    To expand what ikegami said (it took me a second to see the bug as well; this is a subtle one), perl interprets the bareword main to mean the function you declared as main, not the implicit package of main. This is documented behavior.

    You can fix it by adding the postfix double-colon sigil to disambiguate the bareword main as a package name, by moving the declaration of foo to before the declaration of main, or by removing the name collision.

Re: Class->can() bug or user error
by ikegami (Patriarch) on Jul 15, 2011 at 19:17 UTC

    The code doesn't do what you want, so of course there's a bug. The bug is in your code, though. Fixes:

    'main'->can("bar")
    main::->can("bar")
Re: Class->can() bug or user error
by runrig (Abbot) on Jul 18, 2011 at 16:00 UTC
    And B::Deparse confirms what ikegami and chromatic say above (which is what I should have checked in the first place):
    $ perl -MO=Deparse tst my $i = 0; main(); sub main { use warnings; use strict 'refs'; print "${i}: main()\n"; exit if $i++ > 10; print "Calling foo()\n"; foo(); } sub foo { use warnings; use strict 'refs'; print "foo()\n"; return unless my $fn = main()->can('bar'); print "We can bar\n"; &$fn(); }