Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re: use and require inside subs

by tachyon (Chancellor)
on Nov 02, 2004 at 23:37 UTC ( #404783=note: print w/replies, xml ) Need Help??


in reply to use and require inside subs

You seem to be making a distinction between subroutines in .pl files and modules. There is no such distinction. Modules are typically just a collection of subroutines/functions/methods/widgets - call them what you will. See Simple Module Tutorial. Anyway besides suggesting that you put everyting into modules for consistency and simplicity's sake the main difference between use and require is that use does a require PLUS calls the modules import function. Never seen a module with an import() function? That is becaue it is inherited from Exporter Depending on what the module exports by default (in @EXPORT) and what you ask for (in @EXPORT_OK) zero or more functions/subroutines will become available via their unqualified name ie you can call somefunction(). You can *always* call Some::Module::somefunction() by its fully qualified name, regardless of whether or not you have imported it. The only pre-requisite is that you have used or required that module first.

The other significant difference between use and require is that use happens at compile time. require happens at runtime as Perl stumbles across it. require is almost the same as do (it uses it), except it will search @INC for you. For example you can do (not recommended) this to effectively get very similar results to useing a module:

do 'd:/perl/lib/Data/Dumper.pm'; Data::Dumper->import(); print Dumper(\@INC,\%INC);

So what do I personally do? Almost all code is in modules. In a given script/module I will use any other Module I know I will need, and import the functions that always get used. In any given function, if it is possible that a module has not been used and/or the required function imported I will have:

sub widget { # blah require Some::Module; my $result = Some::Module::somefunction(@args);

cheers

tachyon

Replies are listed 'Best First'.
Re^2: use and require inside subs
by elwarren (Curate) on Nov 03, 2004 at 00:48 UTC
    I thought I knew this, but why do I put my use statements inside if/then if it happens at compile time?
    use warnings; use strict; my $config; if ($^O eq 'MSWin32') { use Win32::TieRegistry( Delimiter=>"/", ArrayValues=>0 ); # load $config from registry } else { # else load $config from flat files }
    Too tired to think for myself tonight.
        Even more convincing is to put the print statement before the if statement.
        print "$_\n" for keys %INC; if (0) { print "This block is happening!\n"; use Win32; }

        --
        [ e d @ h a l l e y . c c ]

        hehe, so maybe I don't run that cross-platform code on other platforms recently :-) I'll have to dig it up and see what I actually did now.

        Cheers
      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

        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
        I think you mean
        require Win32::TieRegistry; Win32::TieRegistry::->import(Delimiter=>"/", ArrayValues=>0 );
        since the way you have it, perl will attempt to use that module even not on Win32.

        Another way:

        use if $^O eq 'MSWin32', "Win32::TieRegistry", Delimiter=>"/", ArrayValues=>0;
        if you have if.
        But how do you know that, its not like this is documented somewhere?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://404783]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2020-08-13 00:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which rocket would you take to Mars?










    Results (68 votes). Check out past polls.

    Notices?