Module setup style and BEGIN blocks

Module setup style and BEGIN blocks

am 08.05.2006 02:53:50 von tim.largy

When writing Perl modules, there are several templates floating around
(in books, man pages, and so on) and one major difference between them
is in the use of BEGIN blocks. I don't understand why some templates
put Exporter-related things in the BEGIN block, and others do not.
Consider the template provided by the perlmod manpage :

package Some::Module; # assumes Some/Module.pm

use strict;
use warnings;

BEGIN {
use Exporter ();
our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);

# set the version for version checking
$VERSION = 1.00;
# if using RCS/CVS, this may be preferred
$VERSION = sprintf "%d.%03d", q$Revision: 1.1 $ =~
/(\d+)/g;

@ISA = qw(Exporter);
@EXPORT = qw(&func1 &func2 &func4);
%EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2!
],

# your exported package globals go here,
# as well as any optionally exported functions
@EXPORT_OK = qw($Var1 %Hashit &func3);
}
our @EXPORT_OK;

[remainder clipped]

Why put all of these things in the BEGIN block instead of outside, like
the template in the _Perl Cookbook_, 2nd Edition (O'Reilly)?

Tim

Re: Module setup style and BEGIN blocks

am 10.05.2006 04:56:37 von ermeyers

tim.largy@gmail.com wrote:

> When writing Perl modules, there are several templates floating around
> (in books, man pages, and so on) and one major difference between them
> is in the use of BEGIN blocks. I don't understand why some templates
> put Exporter-related things in the BEGIN block, and others do not.
> Consider the template provided by the perlmod manpage :
>
> package Some::Module; # assumes Some/Module.pm
>
> use strict;
> use warnings;
>
> BEGIN {
> use Exporter ();
> our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
>
> # set the version for version checking
> $VERSION = 1.00;
> # if using RCS/CVS, this may be preferred
> $VERSION = sprintf "%d.%03d", q$Revision: 1.1 $ =~
> /(\d+)/g;
>
> @ISA = qw(Exporter);
> @EXPORT = qw(&func1 &func2 &func4);
> %EXPORT_TAGS = ( ); # eg: TAG => [ qw!name1 name2!
> ],
>
> # your exported package globals go here,
> # as well as any optionally exported functions
> @EXPORT_OK = qw($Var1 %Hashit &func3);
> }
> our @EXPORT_OK;
>
> [remainder clipped]
>
> Why put all of these things in the BEGIN block instead of outside, like
> the template in the _Perl Cookbook_, 2nd Edition (O'Reilly)?
>
> Tim

Hi Tim,

First things first.

Everything you do should be Focused on Function(ality), Readability and
Maintainability, with a little Class, Humor and Style thrown into your code
to make it enjoyable Function and Edutainment for yourself and others. I
don't believe that Good Style is as important to emulate, as is Good
Function and Good Timing, so forget the Style for the most part. If you
like the compact K&R Style, then God Bless you, but I like the better
Readability of the ANSI Style.

If you look at 'perldoc -f use,' the use just means BEGIN { require Module;
import Module LIST; }. So, BEGIN { use Exporter qw() }, just means BEGIN
{ BEGIN{ require Exporter; import Exporter qw() } }.

If you specify just 'require Exporter;,' then you just need to access
Exporter components as 'Exporter::component,' rather than just specifying
'component,' if you had just specified 'import Exporter qw(component);.'

Just got that?

Except, and there is only one reason for an except, the BEGIN or END.

BEGIN {
##
## K&R Style here, not ANSI. Sometimes BEGIN/END only Function this way.
##

##
## In the Beginning.
##
## God ("Mr./The" Exporter) may have said something like:
##

require Exporter; import Exporter;

##
## This is my Dawning Moment of Creation. I BEGIN! Thanks God!
##
## I hope that I may get Blessed someday, and someone uses me for Good.
##
## I'm now using all of the Exporter components that I've been given.
##
## I require Exporter, so that I get it from @INC, and I import Exporter
## to get to access its components on a first name basis.
##
## Everything in @Exporter::EXPORT I got by name with the import.
## Everything in @Exporter::EXPORT_OK I'll get by name, as needed.
##

##
## Exporter, VERSION or VCS related stuff here.
##
## I'm becoming another version of an Exporter, and
## I'll have a real VERSION someday, because I'll be Complex.
##
## If I'm not Complex, I'll have one.
##

} ## end BEGIN

END
{ ##<-- this could be a Dis-Functional Style of END {} / BEGIN {}.
die( "Sorry, no will:$!" );
} ## end END

That is perfect! I was so nice to it. But the code Style above was faulty.

You should use 'my' instead of 'our,' because these are 'my' components and
no one else's by a Gentlemen's Agreement not to invade each others
namespace. Except, if you are Agreegating intentionally.

You should not have anything in @EXPORT, but the things that you just feel
compelled to force into another person's namespace. It's forcing yourself.
Instead the @EXPORT_OK, let's us take what we want, as we need it from you.

@EXPORT_TAGS lets you define classes of imported components, when asked
specifically for a specific class of components, like ':all.' When the
namespace above asks for ':all,' then you didn't force your components upon
their namespace, because the asked for ':all' of them.

I hope this helps you to understand it.

May God Bless You,

Eric
An Exporter.