Watch out for side effects with `use VERSION`

To specify that you wanted to use at least a particular version of Perl, you specified that version with the use built-in:

use VERSION;

We covered this in Item 83: Limit your distributions to the right platforms, and we mentioned that it might invoke side effects. We didn’t get into the details in that Item though. As of Perl 5.10, this introduces side effects that you might not want.

Merely specifying a Perl version prior to 5.10 (well, actually before 5.9.5, the development track that led to 5.10) does nothing other than check the version you specify against the interpreter version. If the version you specify is equal to or greater than the interpreter version, your program continues. If not, it dies:

use 5.008;  # needs perl5.008000 or later

This works with require too:

require 5.008;  # needs perl5.008000 or later

However, use is a compile-time function and require is a run-time function. By the time you hit that require, perl has already compiled your program up to that point or died trying as it ran into unknown features. Code may have already run, despite using an inappropriate version of perl. You want to impose your version restriction as soon as possible.

You might think that you can fix this with a BEGIN block which compiles and immediately runs the code so you get the ordering right:

BEGIN { require 5.010; }

However, this also pulls in the new features for that version, at least in Perls 5.10 and 5.12, although that might be a bug. Even if it is, it still is what it is and you need to watch out for it.

use 5.010

With Perl 5.10, you get three side effects with use 5.010. Starting with that version, use-ing the version also pulls in the new features for that version. Obstensibly, that keeps programs designed for earlier versions breaking as newer perls add keywords, but it also tries to enforce the current philosophy of good programming on you.

Perl 5.10 introduces say, state, and given-which, which you import implicitly when you say use 5.010:

use 5.010;
say 'I can use Switch!';  # imported say()

given ($ARGV[0]) {        # imported given()
	when( defined ) { some_sub() }
	};

sub some_sub {
	state $n = 0;         # imported state()
	say "$n: got a defined argument";
	}

If you want to insist on Perl 5.010 but not use its new features, perhaps because that’s the installation with the necessary modules, you can unimport the side effects immediately with the new feature pragma:

use 5.010;     # implicit imports
no feature;    # take it right back again

# you're own version of say()
sub say {
	# something that you want to do
	}

If you only want some of the new features, you can unimport the ones that you don’t want:

use 5.010;
no feature qw(say);   # leaves state() and given()

sub say {
	# something that you want to do
	}

use 5.012

Perl 5.12 includes two more side effects for use VERSION. The unicode_strings feature treats all strings outside of bytes and locale scopes as Unicode strings. Additionally, use 5.012 automatically turns on strict:

use 5.012;
# now strictures are on

$foo = 1;   # compile-time error!

Again, you can’t get around this by using require because it still turns on the new features and enables strict:

BEGIN { require 5.012 }

$foo = 1;  # still a compile-time error

If, for some odd and dangerous reason you don’t want strict on by default, you can turn it off yourself, even though unimporting it doesn’t give you the warning that you’ve left the paved roads, you’ve just violated your rental car contract, and there’s a chainsaw massacrer waiting for you:

use 5.012;
no feature;
no strict;

my $foo = 1;   

$fo0++;  # sure, go ahead and make that error

A workaround to restrict perl versions

There’s a way around all of this, and it’s to not restrict the version with use if that’s the only thing that you want to do. Instead, you can check the value of the $] variable, just like the various examples you saw in Item 83:

BEGIN {
	die "Unsupported version" 
		unless $] >= 5.010 and $] < 5.011
	}

This has the added benefit of restricting the upper acceptable perl version.

Things to remember

  • use VERSION imports new features since Perl 5.9.5.
  • BEGIN { require VERSION } still imports new features
  • Use no feature or no strict to unimport unwanted features.
  • Restrict the perl version with $].
Leave a comment

1 Comments.

  1. There has been some talk on P5P of changing the way `use 5.xxx` works, so that it gets converted at compile time to `BEGIN { require 5.xxx; require feature; feature->import(“5.x”); }` or the roughly equivalent `BEGIN{ require 5.xxx; $^H{‘feature_unicode’} = q(1); $^H{‘feature_say’} = q(1); $^H{‘feature_state’} = q(1); $^H{‘feature_switch’} = q(1); }

    This is arguably how it should have been implemented to start with.

Leave a Reply


[ Ctrl + Enter ]

7ads6x98y