http://www.perlmonks.org?node_id=740739


in reply to Getting file and line number where a subroutine is declared

It works better if it's rearranged.

use B; $\="\n"; package Foo; # line 23 'bin/some_file.pl' sub some_sub { warn "Got to here"; } # line 99 'bin/some_code.pl' print "some_sub: ",B::svref_2object(\&Foo::some_sub)->GV->LINE; { no strict 'refs'; print "some_other_sub: ",B::svref_2object(\*{'Foo::some_other_sub' +})->LINE; } Foo::some_sub(); __END__ some_sub: 25 some_other_sub: 102 Got to here at 'bin/some_file.pl' line 24.

This code is a little over my head to be honest, but my guess is that your references to Foo::some_sub in the no strict 'refs' block are creating the darned thing right there on the spot. Perhaps another monk can explain this behavior.

I don't know if this is helpful or not, but I found it interesting.

Replies are listed 'Best First'.
Re^2: Getting file and line number where a subroutine is declared
by ikegami (Patriarch) on Feb 02, 2009 at 16:54 UTC

    Perhaps another monk can explain this behavior.

    \&Foo::some_sub autovivifies a sub stub at run-time (just like sub Foo::some_sub; would at compile-time).

    $ perl -le' print(exists(&Foo::some_sub)?1:0, defined(&Foo::some_sub)?1:0); $x=\&Foo::some_sub; print(exists(&Foo::some_sub)?1:0, defined(&Foo::some_sub)?1:0); eval "sub Foo::some_sub { print \"foo\" }"; print(exists(&Foo::some_sub)?1:0, defined(&Foo::some_sub)?1:0); $x->(); ' 00 10 11 foo

    As demonstrated, this permits the reference to be taken to a sub that has yet to be defined.

    \&Foo::some_sub creates glob entry at compile-time.

    $ perl -le' print(exists($Foo::{not_a_sub})?1:0); print(exists($Foo::{some_sub})?1:0); $x=\&Foo::some_sub; ' 0 1

      \&Foo::some_sub autovivifies a sub stub at run-time (just like sub Foo::some_sub; would at compile-time).

      So it will work fine as long as we don't make any reference to the sub in any compiled code that comes before the definition.

      use B; $\="\n"; # line 99 'bin/some_code.pl' { no strict 'refs'; print B::svref_2object(eval q(\\*{'Foo::some_sub'}))->LINE; print B::svref_2object(eval q(\\&Foo::some_sub))->GV->LINE; } eval q{Foo::some_sub()}; package Foo; # line 23 'bin/some_file.pl' sub some_sub { warn "Got to here"; } __END__ 25 25 Got to here at 'bin/some_file.pl' line 24.

      Of course, string eval has a code smell, but so does no strict 'refs'.

        Symbolic refs will do instead of eval.

        { no strict 'refs'; my $name = 'Foo::some_sub'; print B::svref_2object(\*$name)->LINE; print B::svref_2object(\&$name)->GV->LINE; $name->(); }

        It can be done with strict refs too.

        my $glob = $::{'Foo::'}{some_sub}; print B::svref_2object(\*$glob)->LINE; print B::svref_2object(\&$glob)->GV->LINE; $glob->();