If you read perlmod's "BEGIN, UNITCHECK, CHECK, INIT, and END", you'll learn that Perl has several special named code blocks that let you run arbitrary code at various points in the compilation and execution process.
David Mertens wrote about this recently in Lexical closures with END blocks warn, but Just Work. His post explains a couple of features of these blocks but doesn't tell the entire story.
These code blocks are code blocks in the same way that function definitions are code blocks. They exist in lexical environments. They provide their own lexical environments. They don't get stored in the symbol table the way you might expect a normal function does, but they have their lexical bindings created and fixed up in the same way that named functions do. In fact, you can just as easily write them:
sub BEGIN { say 'In first BEGIN' }
BEGIN { say 'In second BEGIN' }
The declaration is the same either way. That ought to make the behavior David wrote about more clear; the error message he saw is the same as the one you get when you declare a function within another function. Yes, the inner function will close over the lexical scope of the first function, but they won't share inner lexicals. If you've done much work with closures in Perl, that ought to make sense to you.
You might find this surprising though:
#!/usr/bin/env perl
use Modern::Perl;
exit main( @ARGV );
sub main {
foo();
bar();
baz();
Foo->new;
return 0;
}
AUTOLOAD {
our $AUTOLOAD;
say "Hit autoload for $AUTOLOAD";
}
package Foo;
sub new { bless {}, $_[0] }
DESTROY { say 'Destroying!' }
Perl's tokenizer (toke.c in the Perl source code tree) has special
cases for the five special code blocks as well as
AUTOLOAD
and DESTROY
. This allows you to provide or
elide the leading sub
from the declaration of any of the five code
blocks, the AUTOLOAD
function, or the DESTROY
method—though for the sake of clarity, you should probably use sub
on
the latter two and not on the former five.
(You may be able to make the philosophical argument to treat these seven
code blocks in the same way because they never get called directly with
arguments; in most normal code, you expect Perl's runtime to call them
implicitly. That falls apart only a little bit because a subclass's
DESTROY
might want to redispatch upward, but Moose's DEMOLISH
strategy solves
that anyhow.)