Item 59: Initialize with BEGIN


Item 59: Initialize with BEGIN ; finish with END .

Often you will need to initialize subroutines and/or packages before they are first used. Perl provides a mechanism, BEGIN blocks, that allows you to execute initialization code at program start-up. Perl also provides a complementary mechanism, END , that allows you to execute code just before program termination.

BEGIN

A BEGIN block encloses code that is to be executed immediately after it is compiledbefore any following code is compiled. For example, you can use BEGIN to initialize a variable that a subroutine later will use:

Use BEGIN blocks to enclose initialization code.

 BEGIN {    @dow = qw(Sun Mon Tue Wed Thu Fri Sat);  }  sub dow {    $dow[ $_[0] % 7 ];  } 

Initialize @dow at start-up.

Because the contents of BEGIN blocks are compiled and executed before any "normal" code, it generally does not matter where a BEGIN block goes. In many cases, the best place to put a BEGIN block is inside the subroutine or other code that needs it:

Place BEGIN blocks where they are most convenient .

 sub dow {    BEGIN {     @dow = qw(Sun Mon Tue Wed Thu Fri Sat);    }    $dow[ $_[0] % 7 ];  } 

It doesn't matter where the BEGIN block goesit still gets executed first (and only once). Now you can cut and paste the subroutine without fear of misplacing the BEGIN block.

BEGIN blocks can also be used in combination with my to create private static variables like those in C (see also Item 29):

Use my and BEGIN blocks to create static variables.

 BEGIN {    my @dow =      qw(Sun Mon Tue Wed Thu Fri Sat); 

@dow is local to this blockand is initialized at compile time.

 sub dow {      $dow[ $_[0] % 7 ];    }  } 

Only the subroutine dow has access to @dow @dow is invisible to the rest of the program.

You can even create shared static variables:

Create shared static variables with my and BEGIN blocks.

 BEGIN {    my $static = 10;    sub inc_static {      ++$static;    }    sub dec_static {      --$static;    }  } 

$static is shared between inc_static and dec_static . It is not visible to any other part of the program.

 print "inc_static = ", inc_static, "\n";  print "dec_static = ", dec_static, "\n"; 

inc_static = 11

dec_static = 10

Because code in a BEGIN block is compiled and executed immediately as it is encountered during the compile phase, code in a BEGIN block can alter compile-time semantics. In particular, a BEGIN block can create and define functions that work as list operatorsjust as though they had been declared in the program text (also see Item 10):

 eval q{    sub func_1 {print "f1: @_\n"}  }; 

Define func_1 at run time.

 BEGIN {    eval q{      sub func_2 {print "f2: @_\n"}    };  }; 

Define func_2 in an eval block, but as the code is being compiled.

 func_1(1..4); 

Parenthesized syntax is fine (also &func_1() is fine).

 func_2 1..4; 

List operator is OK, because func_2 was defined before this line was compiled.

 func_1 1..4; 

List operator NOT OK, because func_1 was not defined before this line was compiled.

Because require (see Item 54) is basically a form of eval , we can use BEGIN blocks to "import" functions from files containing Perl source code:

Combining BEGIN with require

File func1.pl

 sub func_1 {    print "func_1\n"  }  1; 

Same as in example above, but now the sub is defined in a separate file.

Main program

 #!/usr/local/bin/perl 

Or wherever Perl is.

 BEGIN {    require "func1.pl";  } 

eval contents of func1.pl , but at compile time.

 func_1; 

Because we wrapped require in BEGIN , list operator syntax is OK.

In fact, this is the mechanism employed by Perl's use directive, and it is the basis for writing modules in Perl 5:

 BEGIN {    require "Module.pm";    import Module;  } 

Same as use Module .

See Item 42 for more about Perl modules.

END

END blocks enclose code that will be executed just as a Perl program terminates. END blocks are useful for cleaning upgetting rid of lockfiles, releasing semaphores, and so forth:

Use END locks to enclose program clean-up code.

 END {    unlink glob "/tmp/$prog_name.*";  } 

Remove scratch files.

END blocks are executed during any "planned" terminationthe end of the script, exit , die , and so on. Multiple END blocks are executed in reverse of the order in which they were encountered during compilation.

END blocks are not executed in other casesuncaught signals, Perl panics, before exec , et cetera.



Effective Perl Programming. Writing Better Programs with Perl
Effective Perl Programming: Writing Better Programs with Perl
ISBN: 0201419750
EAN: 2147483647
Year: 1996
Pages: 116

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net