Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

BEGIN { } block

by bob_dobalina (Sexton)
on Aug 07, 2009 at 15:48 UTC ( #786823=perlquestion: print w/ replies, xml ) Need Help??
bob_dobalina has asked for the wisdom of the Perl Monks concerning the following question:

when would i want to use a BEGIN { } block, as in a real world example of why i'd want to have something evaluated when it's "use"d? Thanks!

Comment on BEGIN { } block
Re: BEGIN { } block
by BioLion (Curate) on Aug 07, 2009 at 16:11 UTC

    Because BEGIN blocks are executed ASAP ( perlmod ), i use them to change @INC to allow me to load local modules :

    BEGIN { unshift @INC, "$ENV{HOME}/Desktop/CODE/lib"; ## include local lib };

    I am sure there are better examples out there though!

    Just a something something...
Re: BEGIN { } block
by biohisham (Priest) on Aug 07, 2009 at 16:16 UTC
    because BEGING{} is an implicitly called subroutine in Perl, it can hold any initialization code, You would probably need to use BEGIN{} as a package constructor
    package foo; BEGIN{ $text = "Hello\n"; } sub subroutine {print $text} return 1;
    now after having initialized $text you can use it in code that calls foo code
    require foo; foo::subroutine(); #will print Hello
    Other features of BEGIN{}:
    • it is run early when your code is compiled (even before the rest of the file is parsed).
    • you can use multiple BEGIN{} in the package and Perl will execute them by order of encounter.
    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind
      1. You mean just BEGIN, not sub BEGIN. You're also missing a semicolon after package foo.
      2. You should be naming your package files with extension .pm, not .pl. You also don't need to specify the extension when require- or use-ing.
      3. You define subroutine in package foo, but try to use the subroutine from package1.
      4. The biggest one: The behaviour you describe has nothing to do with BEGIN. It works just the same if you remove the BEGIN {} block.

      UPDATE: AnomalousMonk points out (indirectly) that my point (4) is “only just” correct—the very early initialisation provided by BEGIN {} can certainly be useful if you might call a subroutine before some variables in it would be initialised by the normal flow of code.

        Thanks for the tips, I have taken due action, and your clarification is appreciated, as for note number 4 , I was seeking simplicity by showing a behavior that is relatively easier to correlate with and that is general, What I have presented has to do more with Packages, just to show one side of the many places BEGIN{} can come in handy and it just shows where BEGIN{} block can feature in a Package...
        Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind
Re: BEGIN { } block
by JadeNB (Chaplain) on Aug 07, 2009 at 16:26 UTC
    The thing that made this clear for me is realising that useing a standard Exporter-derived module absolutely must be done at compile time.
    a my ($b, $c)
    doesn't compile, but
    use A qw/a/; a my ($b, $c);
    does (assuming package A exports subroutine a). How can the use statement affect compilation? It couldn't, without BEGIN {}!

    The point is that Exporter->import defines a (probably via some clever version of eval 'sub ' . caller . '::' . $to_be_imported *) at compile time.

    For an even subtler example of the nastiness that can occur, note that

    my ( $b, $c ); a $b, $c;
    does compile, but not as you'd expect—the ‘indirect object’ syntax causes it to be compiled as
    $b->a($c)

    * At least, I think that that's what happens; I got tired reading the Exporter source and didn't find out for sure. :-)

Re: BEGIN { } block
by AnomalousMonk (Abbot) on Aug 07, 2009 at 17:59 UTC
    Prior to Perl version 5.10, a  BEGIN block could also be used to initialize 'static' lexical variables in a subroutine closure. The  state variable of 5.10 implements 'static' lexicals. See Persistent Private Variables in perlsub.

    Prior to 5.10:

    >perl -wMstrict -le "S(); S(); { my $s = 'hiya'; sub S { print $s++ } } S(); " 0 1 hiya >perl -wMstrict -le "S(); S(); BEGIN { my $s = 'hiya'; sub S { print $s++ } } S(); " hiya hiyb hiyc
    With 5.10 (the -E switch enables 5.10 features):
    >perl -wMstrict -lE "S(); S(); sub S { state $s = 'hiya'; print $s++ } S(); " hiya hiyb hiyc
Re: BEGIN { } block
by shawnhcorey (Pilgrim) on Aug 07, 2009 at 21:07 UTC

    The Poor Man's Grep: for use on Windows when you have Perl but not grep(1).

    perl -nle "BEGIN{@ARGV=map{glob}@ARGV}/PATTERN/&&print" <files> ...

    Replace PATTERN with the pattern you want to find.

    Here, the BEGIN{} is used to convert any wildcards in the <files> into real file names.

      The poor man's grep on Windows is findstr.
        Or grep, or ack (designed as a replacement for 99% of the uses of grep).
Re: BEGIN { } block
by jgamble (Pilgrim) on Aug 07, 2009 at 23:59 UTC
    I've used it to calculate epsilon when my module gets loaded.
Re: BEGIN { } block
by ggvaidya (Pilgrim) on Aug 09, 2009 at 10:48 UTC

    Remember that use statements are implicitly emBEGINned - they're evaluated as soon as perl understands that they're there. So BEGIN blocks are actually evaluated not just when use is used, but before any other (non-BEGIN) code executes at all.

    I've written a web application which uses BEGIN {} blocks to set up signal handlers for die()/warn() calls to do various site-specific stuff with them (like e-mailing the errors to the system admin so he knows there's problem afoot, and silencing warnings on the production site but making them fatal otherwise).

Re: BEGIN { } block
by moritz (Cardinal) on Aug 09, 2009 at 10:52 UTC
    As a general resource you can use google code search to find real world examples of particular constructs.
Re: BEGIN { } block
by busunsl (Vicar) on Aug 11, 2009 at 14:22 UTC
    Sometimes you have to make sure that some environment variables are set.

    For example some settings for a connection to a database:

    BEGIN { $ENV{NLS_LANG} = 'GERMAN'; $ENV{NLS_DATE_FORMAT} = 'YYYY-MM-DD'; $ENV{NLS_TIMESTAMP_FORMAT} = 'YYYY-MM-DD HH24:MI:SS'; } use DBI; my $dbh = DBI->connect('dbi:Oracle:db', 'user', 'pw');

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://786823]
Front-paged by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (9)
As of 2014-12-22 17:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (124 votes), past polls