Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BEGIN,CHECK,INIT& END blocks in Perl

Tags:

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.

like image 581
Subhayan Bhattacharya Avatar asked Sep 07 '25 12:09

Subhayan Bhattacharya


2 Answers

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.

like image 95
zdim Avatar answered Sep 10 '25 01:09

zdim


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

like image 44
Borodin Avatar answered Sep 10 '25 03:09

Borodin