Search code examples
perlperl-module

How to include conditionally Perl modules and libraries, as well as Global variables from them


I am developing a Perl script. Inside I use various moudules:

use Module::One;
use Module::Two;
...

I also use global variables from these modules:

$GLOBAL_1 = 1;
$GLOBAL_2 = 1;
...

Let's say that the name of the script is

my_script.pl

Is it possible to include the above-mentioned modules and globals conditionally when passing to the script an argument called 'no_libs', but whenever not passing this argument - not include or use them? Something like that:

perl my_cript.pl no_libs

if ( $ARGV[0] eq 'no_libs' ) {
    use Module::One;
    use Module::Two;
    ...

    $GLOBAL_1 = 1;
    $GLOBAL_2 = 1;
    ...
}

Solution

  • I expect that the example $ARGV[0] eq '...' really stands for more involved processing of the command line arguments, including assignments to variables and such. Then that happens at runtime and you cannot condition use that way, as it runs at compile time.

    The example as stated works at compile time though, in which case use the if pragma

    use if @ARGV && ($ARGV[0] eq 'no_libs'), "Module::One", qw(...);
    

    which has the same effect as use Module::One qw(...) if the condition is true.

    If the decision indeed happens at runtime then you need to use require instead

    if ($no_libs) {
        require Module::One;
        Module::One->import( qw(f1 f2) );  # as in: use Module::One qw(f1 f2);
        ...
    }
    

    The use comes down to require since use Module LIST; means exactly

    BEGIN { require Module; Module->import( LIST ); }

    so you are doing practically the same but at runtime.

    However, global variables can't be imported this way since strict won't have their declarations in time. Thanks to ikegami for the comment. You can use them directly as $Module::One::Var, for our $Var in Module::One, but please see the following comments.

    In general, exporting global variables from modules is not a good practice as it erodes the overall design, by entangling supposedly distinct components and bypassing their interfaces. It may also lead to subtle and hard to detect problems.

    Having globals conditionally seems strange: how do you use them if they may not exist? This can be a confusing design, which can probably be changed.