http://qs1969.pair.com?node_id=404812


in reply to Re^2: use and require inside subs
in thread use and require inside subs

I thought I knew this, but why do I put my use statements inside if/then if it happens at compile time?

As Tachyon points out, you shouldn't. Or at least, run-time statements won't get executed at compile time, so your code won't do what you want.

Remember, the use() command has an implicit BEGIN block around it, which forces the statements to be executed at compile time. The statement:

use module;

is like writing:

BEGIN { require "module.pm;" module::import(); }

So, you have two choices. You can make all the decisions about which code to include at run-time, and use "require" statements.

As ysth points out, something like the following doesn't actually work, though I initially thought it did.

use warnings; use strict; my $config; BEGIN { if ($^O eq 'MSWin32') { use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 ); # load $config from registry } else { # else load $config from flat files } } # end system specific compile time code

Since BEGIN blocks and use statements both now happen at "compile time", the above code should work, right? Nope. There's a specifically defined order to how BEGIN blocks execute, and it's not what I had assumed it was.

Upon a careful reading of the perl module documentation page, (type "perldoc perlmod" to read it), I think I understand how it all works. Comments and corrections are appreciated.

According to the documentation: A "BEGIN" code block is executed as soon as possible, that is, the moment it is completely defined.

The documentation doesn't say exactly what "completely defined" means, but I took it to mean when the end of the BEGIN block is reached, when reading sequentially through the code. This implies that code like this:

BEGIN { print "-one-"; BEGIN { print "-two-"; BEGIN { print "-three-; } # end of block that prints "-three-" } # end of block that prints "-two-" } # end of block that prints "-one-"
should print "-three-two-one", because the end of the block that prints "-three-" is encountered first, then "-two-", then "-one-". This is what happens when I run it, which implies I'm at least close to right.

It also means that when you write a BEGIN block with a "use" statement inside it, the end of the use statement gets reached before the end of the BEGIN block. Since a use statment is really an implied BEGIN block, this means it executes first, before the BEGIN block gets a chance to do anything.

Sorry for any confusion I caused. :-( --
Ytreq Q. Uiop