简体   繁体   中英

BEGIN,CHECK,INIT& END blocks in Perl

As I understand these special functions inside Perl code, BEGIN and CHECK blocks run during the compilation phase while INIT and END blocks run during actual execution phase.

I can understand using these blocks inside actual Perl code (Perl libraries) but what about using them inside modules? Is that possible?

Since when we use use <Module-name> the module is compiled, so in effect BEGIN and CHECK blocks run. But how will the INIT and END blocks run since module code I don't think is run in the true sense. We only use certain functions from inside the modules.

Short The special code blocks in packages loaded via use are processed and run (or scheduled to run) as encoutered, in the same way and order as in main:: , since use itself is a BEGIN block.


Excellent documentation on this can be found in perlmod . From this 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.

Since the use statements are BEGIN blocks they run as soon as encountered. From use

It is exactly equivalent to

 BEGIN { require Module; Module->import( LIST ); } 

So the BEGIN blocks in a package run in-line with others, as they are encountered. The END blocks in a package are then also compiled in the same order, as well as the other special blocks. As for the order of (eventual) execution

An END code block is executed as late as possible ...

and

You may have multiple END blocks within a file--they will execute in reverse order of definition; that is: last in, first out (LIFO)

The order of compilation and execution of INIT and CHECK blocks follows suit.


Here is some code to demonstrate these special code blocks used in a package.

File PackageBlocks.pm

package PackageBlocks;
use warnings;

BEGIN { print "BEGIN block in the package\n" }
INIT  { print "INIT  block in the package\n" }
END   { print "END   block in the package\n" }
1;

The main script

use warnings;

BEGIN { print "BEGIN in main script.\n" }

print "Running in the main.\n";

INIT { print "INIT in main script.\n" }

use PackageBlocks;

END   { print "END in main script.\n" }
BEGIN { print "BEGIN in main script, after package is loaded.\n" }

print "After use PackageBlocks.\n";

Output

BEGIN in main script.
BEGIN block in the package
BEGIN in main script, after package is loaded.
INIT in main script.
INIT block in the package
Running in the main.
After use PackageBlocks.
END in main script.
END block in the package

The BEGIN block in the package runs in order of appearance, in comparison with the ones in main:: , and before INIT . The END block runs at end, and the one in the package runs after the one in main:: , since the use comes before it in this example.

This is very easy to test for yourself

use Module (and require EXPR and do EXPR and eval EXPR ) compile the Perl code and then immediately run it

That is where the 1; at the end of most modules is picked up. If executing the module's code after compiling it doesn't return a true value then require will fail

Admittedly there usually isn't much use for an INIT or an END block, because the run-time phase is so intimately tied to the compilation, and because modules are generally about defining subroutines, but the option is there if you want it

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM