I would like to conditional load a package if the program name is a test script ending in .t.
However, I'm running into a bug where use if fails when the condition is a regex. I've tested this in Perl 5.10 and 5.16.
The following is my test script ending in .t:
#!/usr/bin/env perl
use v5.10;
BEGIN { say "\$0 is '$0'" }
use if $0 =~ /\.t\z/, 'List::Util', ('pairmap');
say "List::Util is " . ( $INC{"List/Util.pm"} ? '' : 'NOT ' ) . 'included';
Outputs:
$ ./test.t
$0 is './test.t'
List::Util is included
However, the same file with a .pl extension fails:
$ ./test.pl
$0 is './test.pl'
Can't locate pairmap.pm in @INC (@INC contains: /usr/lib64/perl5/5.10.0 /usr/lib64/perl5 /usr/local/share/perl5/x86_64-linux-thread-multi /usr/local/share/perl5 /usr/local/lib64/perl5 /usr/share/perl5 /usr/local/lib64/perl5 /usr/local/share/perl5 /usr/lib64/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib64/perl5 /usr/share/perl5 .) at /usr/share/perl5/if.pm line 13.
BEGIN failed--compilation aborted at ./test.pl line 7.
I can coerce the code into working if I double bang the regex or change it to a substr comparison:
use if !!( $0 =~ /\.t\z/ ), 'List::Util', ('pairmap');
use if substr( $0, -2 ) eq '.t', 'List::Util', ('pairmap');
Outputs:
$ ./test.pl
$0 is './test.pl'
List::Util is NOT included
Is this a known bug? If so, in what version was it fixed?
This is a bug in your code.
The argument list after use MODULE
is in, well, list context.
m//
in list context returns a list of captured strings if successful (or 1
if the regex contains no capturing groups), or the empty list on failure.
Thus:
use if "test.pl" =~ /\.t\z/, 'List::Util', ('pairmap');
is equivalent to
use if (), 'List::Util', ('pairmap');
(The match failed, so an empty list is returned.)
,
in list context is the list concatenation operator, so this gives:
use if 'List::Util', 'pairmap';
'List::Util'
is a true value, so this ultimately ends up loading pairmap.pm
:
use pairmap;
The fix is to give the match scalar context:
use if scalar($0 =~ /\.t\z/), 'List::Util', 'pairmap';
(!
also supplies scalar context to its operand, so !!
has the same effect.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With