Why I can get subroutine address before it is declared without error?

157 Views Asked by At

I have next program:

use warnings;
use strict;

BEGIN {
    print \&mysub;
}


sub mysub {};

print \&mysub;

Its output:

CODE(0x118e890)CODE(0x118e890)

The BEGIN block is processed in compile time. At that point definition of sub mysub is not seen by compiler yet. But program still prints right subroutine address, which it will have when defined.

Why I do not get error here? Is this some sort of autovivification?

2

There are 2 best solutions below

2
ikegami On BEST ANSWER

Yes, this is a form of autovivification. A stub is created when a reference to the sub is required and the sub doesn't exist.

use strict;
use warnings qw( all );
use feature qw( say );

sub test {
   say  defined(&mysub) ? "defined (".\&mysub.")"
      : exists(&mysub)  ? "exists (".\&mysub.")"
      :                   "doesn't exist";
}

test();
my $ref = \&mysub;
test();
eval("sub mysub { }  1") or die($@);
test();

Output:

doesn't exist
exists (CODE(0xab8cd8))
defined (CODE(0xab8cd8))
1
larsen On

Very interesting question. I'm writing this as an answer instead of a comment because it will be rather long, but there are still some bits I'm not entirely sure about.

I believe your intuition is correct and that it is a form of autovivification.

Devel::Peek can spread more light on what's happening.

I changed your code a little bit:

use warnings;
use strict;
use Devel::Peek;

$|++;

BEGIN {
  Dump( \&mysub );
  print \&mysub;
};

sub mysub {};

Dump( \&mysub );
print \&mysub;

I added $|++ so that buffering won't be cause of confusions, and added calls to Devel::Peek::Dump to look into the reference \&mysub. Here the output on my system:

SV = IV(0x2628628) at 0x2628638
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x26286e0
  SV = PVCV(0x2640750) at 0x26286e0
    REFCNT = 2
    FLAGS = (DYNFILE)
    COMP_STASH = 0x25ffdb0  "main"
    ROOT = 0x0
    GVGV::GV = 0x26287a0    "main" :: "mysub"
    FILE = "/tmp/autov.pl"
    DEPTH = 0
    FLAGS = 0x1000
    OUTSIDE_SEQ = 0
    PADLIST = 0x0
    OUTSIDE = 0x0 (null)
CODE(0x26286e0)SV = IV(0x25fff20) at 0x25fff30
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x26286e0
  SV = PVCV(0x2640750) at 0x26286e0
    REFCNT = 2
    FLAGS = (DYNFILE)
    COMP_STASH = 0x25ffdb0  "main"
    START = 0x262ea50 ===> 1
    ROOT = 0x262ea10
    GVGV::GV = 0x26287a0    "main" :: "mysub"
    FILE = "/tmp/autov.pl"
    DEPTH = 0
    FLAGS = 0x1000
    OUTSIDE_SEQ = 371
    PADLIST = 0x2648620
    PADNAME = 0x2630180(0x2667f70) PAD = 0x2628770(0x262f020)
    OUTSIDE = 0x2600140 (MAIN)
CODE(0x26286e0)

Note how Dump's output changes between the two calls. The first time Dump is called we just have a reference to a empty scalar. The second time, after the actual definition of the subroutine, you can see the details that pertain to subroutines have been fleshed out: namely PADLIST (now not null), PADNAME and START (I'm not an expert of Perl guts but I think this is the actual "pointer" to the subroutine).

I hope this helps. I'd be interested in knowing what you'll discover if you'll dig deeper in the problem.