Brother Monks,

My question is 'what parts of your code can you assume have already been parsed when you are writing a BEGIN block ?'

I ask because I spent quite some time on the weekend struggling with a package global, set in a BEGIN block, getting clobbered at run time for reasons that are still a little unclear.

Background : I am refactoring some modules, one of which pulls in a configuration file at compile time. That is, clients of this module use it thus

... use Config qw(getConfig); ... my $foo = getConfig('bar'); ...

In Config.pm, the code was originally like this

package Config; my $initialised = 0; sub _initialise { return if $initialised; ... # read config file $initialised++; } _initialise(); sub getConfig{...} ... 1;

This worked, but I changed the $initialised from a my to an our so that there was a way to reload a config file if required (I've changed this to a Reload() method now)

And because I wanted to make clearer that the call to _initialise() was a deliberate decision, I put it in a BEGIN {} block - to me it stands out a lot clearer that the bare statement in the original.

So we have

package Config; our $initialised = 0; sub _initialise { ... # as before } BEGIN { _initialise(); } ... 1;

Now because I like writing correct code, I wrapped all this in a test harness ala Test::More, and took advantage of the fact that $initialised was a package global to write a test like

... use_ok('Config'); is($Config::initialised, 1); # initialisation completed OK

And guess what, I got

t/Config....Name "Config::var" used only once: possible typo at t/Conf +ig.t line 9. # Failed test (t/Config.t at line 9) # got: '0' # expected: '1' # Looks like you failed 1 tests of 2. t/Config....dubious Test returned status 1 (wstat 256, 0x100) DIED. FAILED test 2 Failed 1/2 tests, 50.00% okay Failed Test Stat Wstat Total Fail Failed List of Failed ---------------------------------------------------------------------- +--------- t/Config.t 1 256 2 1 50.00% 2 Failed 1/1 test scripts, 0.00% okay. 1/2 subtests failed, 50.00% okay. make: *** [test_dynamic] Error 2

It looks like the initialisation never happened - but I know it happened because I sprinkled a lot of print's in _initialise() to see it working. So it looks like the our $initialised = 0; is clobbering the value set in the BEGIN, at run time. I hope I'm not using the terms compile/run time too loosely.

After pondering and playing for a while, I came up with this version that seems to be correct.

package Config; sub _initialise { ... # as before } BEGIN { our $initialised = 0; _initialise(); } 1;

This works correctly (though I still get the warning about the var only used once), but the declaration of the our $initialised in the BEGIN looks weird. I suppose if you think about the BEGIN as getting run-time behaviour at compile time, it looks less weird, if you squint.

So if I can't rely on the our $initialised outside the BEGIN as 'existing' when the BEGIN runs, what are the rules about what is in scope before/during/after a BEGIN ?

use brain;


In reply to What can we assume in a BEGIN block ? by leriksen

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.