My Favorite Modules: if
My blog post My Favorite Warnings: redundant
and missing
touched on the use of the if
module. Comments on that post made me think it deserved a top-level treatment, expanding on (though not necessarily improving on) Aristotle's comment.
The if
module is a way to conditionally load another module and call its import()
or unimport()
method. Sample usages are
use if CONDITION, MODULE, ...; # load and import no if CONDITION, MODULE, ...; # load and unimport
In actual use the CONDITION
is an expression that is evaluated at compile time. If that expression is true the named module will be loaded and its import()
or unimport()
method called with whatever arguments were specified. If the condition is false, nothing is done. If MODULE
is a string literal it will have to be quoted, since as far as Perl is concerned it is just another argument.
The usage in the blog that led to this post was
no if "$]" >= 5.022, qw{ warnings redundant missing };
What this does is the equivalent of no warnings qw{ redundant missing };
if compiled on at least Perl 5.22, or nothing at all if compiled on an earlier Perl.
Note that the if
module has nothing to do with the flow-control statement that is spelled the same way, even though use if ...;
looks very like a suffix if
.
I would also like to re-emphasize that everything is evaluated at compile time. Something like
my $condition = some_computation(); my $module = 'Some::Module'; use if $condition, $module;
will not do anything useful, because at compile time the variables are both undef
.
use if some_computation(), 'Some::Module';
will work, but only if the subroutine exists when the use if ...
is compiled.
Of course you can always make it work by sprinkling the requisite amount of
BEGIN
blocks all over the place, but pretty it ain’t:If the
some_computation
sub is not defined at that time then you have to shuffle more code around to get it to be compiled earlier. It can always be made to work, it just gets uglier and uglier.You can even eschew
if.pm
altogether:That particular example is relying on the fact that if you are turning off some warning categories then warnings must have been turned on before so
warnings.pm
is necessarily already loaded and arequire warnings
is therefore not needed. In the general case the code would be uglier still.In summary,
if.pm
is neat.Thank you. I actually considered a
BEGIN
block example, but cut it for reasons I cannot now recall. Your expansion (versus my deleted example) clarifies the "when is it computed" issue, as well as showing what the "do-it-yourself" approach looks like.if
has been core since 5.6.2. Even I (who am fairly conservative in these matters) don't target versions that old any more. So why not use it?Keep in mind that you can't avoid calling import on the module when it is loaded by
if.pm
.Quite right. In that case you need to go with a
BEGIN
block, as documented in the POD.