Bloodnok has asked for the wisdom of the Perl Monks concerning the following question:

Hi again, all you venerable monastery dwellers,

I'm not altogether sure if I've got the right forum for this, but I'm sure one of the janitors will point me/it in the right direction if it looks a little lost;-)

Any road up, my problem now is the oft-quoted equivalent of the use statement, being approximated to...

BEGIN { require module; module->import(); }
Consider the trivial example of module:
package Test1; CHECK { warn "Test1::CHECK1 running" } INIT { warn "Test1::INIT1 running" } UNITCHECK { warn "Test1::UNITCHECK1 running" } sub method { warn "method()" } 1;
and script:
use Test1; Test1->method();
When run, the trivial test script produces the following, expected, output...
Test1::UNITCHECK1 running at Test1.pm line 7. Test1::CHECK1 running at Test1.pm line 3. Test1::INIT1 running at Test1.pm line 5. method() at Test1.pm line 9.
Now, compare and contrast that with changing the script - to..
require Test1; Test1->method();
When run, this results in the following, not so expected, output...
Test1::UNITCHECK1 running at Test1.pm line 7. method() at Test1.pm line 9.
Given that perldoc asserts that
CHECK code blocks are run just after the initial Perl compile phase ends and before the run time begins, in LIFO order
i.e. it makes no mention of this seemingly 'special' behaviour meted out to required modules, am I, yet again, missing something obvious or are the 2 not equivalent in as much as CHECK & INIT blocks in the module are, seemingly, only ever executed if the module is used i.e. they never get executed if the module is only required.
Moreover, if an hierarchy of modules each have CHECK &/or INIT blocks, the hierarchy of blocks is broken wheresoever one of the modules requires another.

.oO(If I am, just for once, right, is there a case for an appropriate update to perlmod ???)

A user level that continues to overstate my experience :-))

Replies are listed 'Best First'.
Re: use equivalent ? I suspect not...
by Fletch (Bishop) on Aug 07, 2008 at 12:46 UTC

    Erm, the BEGIN block is kind of central to the equivalent; it shouldn't be surprising that omitting it changes the sequence things happen. The CHECK and INIT phases have already passed by the time your runtime require executes. Similarly if you've got modules which are used their requires will be done during the compilation phase since by definition use executes then.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Try again - in the expectation that the Node Reaper might step in...

      TFT Fletch - twas the very insight I was too close to see.

      Having said that, does that imply that a run-time require goes thro' the phases anonymously - since as we know, eval { require ... } can be used to detect run-time problems ?

      Update

      Observation withdrawn in the light of further, Fletch originated insight - the key being initial - just goes to show that you only read what you want to c/w what's actually there.

      A user level that continues to overstate my experience :-))

        A BEGIN block will run because those run at compilation time and require drops Perl back into the compiler.

        Likewise an END block will run because that phase hasn't yet occurred when the require is executing.

        However CHECK, which runs (to quote perlmod) "after the initial Perl compile phase", and INIT blocks, which run "just before the Perl runtime begins execution", are not executed since their triggers (post-initial compile phase and prior to the runtime starting) have already passed. But when they're encountered during a BEGIN block by virtue of the code being pulled in via use those phases haven't passed and hence they will be called.

        $ perl -MSpoo -e 0 Spoo BEGIN Spoo CHECK Spoo INIT Spoo END $ perl -e 'require Spoo' Spoo BEGIN Spoo END $ cat Spoo.pm package Spoo; BEGIN { print "Spoo BEGIN\n"; } END { print "Spoo END\n"; } INIT { print "Spoo INIT\n"; } CHECK { print "Spoo CHECK\n"; } 1; __END__

        Think of it this way: BEGIN and friends are kind of special event handler subs called by the Perl runtime. When the given event happens (compilation phase occurs, the runtime is about to start) the runtime looks into the module in question and if it has defined a handler for that event the runtime executes the corresponding sub. It's just that some of the events don't occur for require because they're one time only and that time's passed for the current execution.

        Update: Slight pronoun and wording tweak in last paragraph.

        The cake is a lie.
        The cake is a lie.
        The cake is a lie.

Re: use equivalent ? I suspect not...
by JavaFan (Canon) on Aug 07, 2008 at 14:20 UTC
    Any road up, my problem now is the oft-quoted equivalent of the use statement, being approximated to...
    BEGIN { require module; module->import(); }

    ...

    Now, compare and contrast that with changing the script - to..

    require Test1; Test1->method();
    That ain't the same, is it? If you put your require inside a BEGIN block, you will see the same output.
Re: use equivalent ? I suspect not...
by ysth (Canon) on Aug 08, 2008 at 03:20 UTC
    Consider the trivial example of module:
    package Test1;
    Your trivial example is missing "use warnings;". Use warnings, perhaps especially in trivial examples:
    $ cat Foo.pm use warnings; CHECK { print "in check\n" } INIT { print "in init\n" } 1; $ perl -e'require Foo' Too late to run CHECK block at Foo.pm line 2. Too late to run INIT block at Foo.pm line 3. $ perl -e'use diagnostics; require Foo' Too late to run CHECK block at Foo.pm line 2 (#1) (W void) A CHECK or INIT block is being defined during run time pr +oper, when the opportunity to run them has already passed. Perhaps you +are loading a file with require or do when you should be using use instead. Or perhaps you should put the require or do inside a BEGIN block. Too late to run INIT block at Foo.pm line 3 (#1)
      Yep, you're dead right, guilty as charged;-)

      I do 'normally' use both strict and warnings - not quite sure how this got thro' the net.

      It might even have saved my question - or at least, when asked, my question would have had a far narrower focus.

      A user level that continues to overstate my experience :-))