If if, use use if
There's a common newbie mistake that looks something like this:
if ($ENV{ADVENT_DEBUG}) {
use Devel::ecember 12.25.14;
}
(I call this a newbie mistake to remind myself that I am still, now, and forever a newbie. I still make this mistake when I'm not paying attention.)
The problem, here, is that use
happens at compile time, but if
only controls the flow of the program at run time. This means that our debugger is loaded regardless of the environment. Whoops!
The instinct on how to fix this is often to use a BEGIN
block, but it's not a very good instinct. In Perl, "compile time" and "run time" are relative. Once you've got your if
in a BEGIN
block, your use
is in there too, and now it's still going to run earlier than your conditional!
So, what's a programmer to do?
This is where if
comes in.
use if $ENV{ADVENT_DEBUG}, 'Devel::ecember';
This might look like some weird new form of Perl's postfix conditionals, but it's not weird at all. Or, at least, it's not weird syntax. It's a rarely-seen core library for solving this problem, and it works just like any other module: when you use
it, its import
method is called, and decides what to do next: either use the library you wanted, or not.
You may have noticed that we left something out of our code! We wanted to specify a version number for our debugger: v12.25.14. if
doesn't let us do that, but Exporter comes to our rescue, at least somewhat, here:
use if $ENV{ADVENT_DEBUG}, 'Devel::ecember', '12.25.13';
It's important to realize that if
isn't doing the equivalent of including a version number in a use
statement. What's actually happening is that the string 12.25.13
is being passed to Devel::ecember's import
routine. A little-known feature in Exporter notices when the first argument to import
is version-like, and converts it to a call to the VERSION
method.
What happens if the library you're conditionally loading doesn't use Exporter? Who knows! Probably nothing very good.
There's another complication, too. You can't tell if
to load the library without calling its import
routine. This doesn't come up often, fortunately!
On the other hand, there's another important use case for if
. You can use if when you want to unimport stuff, too. The canonical, gross example of this is:
no if $] >= 5.020, warnings => "experimental::signatures";
Fortunately, that's been rendered obsolete by experimental! Instead, consider:
# It's Christmas! Live a little!
no if (localtime)[4] == 12 - 1 && (localtime)[3] == 25, 'strict';