in reply to Can't call sub within same package in BEGIN block
As others have pointed out, this is simply how BEGIN blocks work -- indeed, how they are defined to work. Here's what perlmod says in the BEGIN, UNITCHECK, CHECK, INIT and END section:
A BEGIN code block is executed as soon as possible, that is, the moment it is completely defined, even before the rest of the containing file (or string) is parsed. You may have multiple BEGIN blocks within a file (or eval'ed string); they will execute in order of definition. Because a BEGIN code block executes immediately, it can pull in definitions of subroutines and such from other files in time to be visible to the rest of the compile and run time. Once a BEGIN has run, it is immediately undefined and any code it used is returned to Perl's memory pool.
Emphasis mine.
This shows why the subroutine has to be defined before the BEGIN block is encountered; when that block is run, the rest of the file, as far as Perl is concerned, does not even exist.
And it cannot be any other way, since one of the reasons for having BEGIN blocks is that they may affect the way the rest of the file is parsed. Source filters would not be possible without BEGIN blocks working this way.
If you need to ensure that certain code is run before other code, but only after the file has been parsed (so that later subroutine definitions etc. are available), use a UNITCHECK, CHECK or INIT block. Quoting the same perldoc again:
UNITCHECK, CHECK and INIT code blocks are useful to catch the transition between the compilation phase and the execution phase of the main program.
UNITCHECK blocks are run just after the unit which defined them has been compiled. The main program file and each module it loads are compilation units, as are string evals, run-time code compiled using the (?{ }) construct in a regex, calls to do FILE, require FILE, and code after the -e switch on the command line.
BEGIN and UNITCHECK blocks are not directly related to the phase of the interpreter. They can be created and executed during any phase.
CHECK code blocks are run just after the initial Perl compile phase ends and before the run time begins, in LIFO order. CHECK code blocks are used in the Perl compiler suite to save the compiled state of the program.
Inside of a CHECK block, the value of ${^GLOBAL_PHASE} will be "CHECK".
INIT blocks are run just before the Perl runtime begins execution, in "first in, first out" (FIFO) order.
Inside of an INIT block, the value of ${^GLOBAL_PHASE} will be "INIT".
The CHECK and INIT blocks in code compiled by require, string do, or string eval will not be executed if they occur after the end of the main compilation phase; that can be a problem in mod_perl and other persistent environments which use those functions to load code at runtime.
You'll also get the added benefit of confusing those who'll read your code later on. :) Everyone knows about BEGIN, but whoever heard of UNITCHECK? (I hadn't, until quite recently.)
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^2: Can't call sub within same package in BEGIN block
by exilepanda (Friar) on Aug 14, 2014 at 11:58 UTC |