views:

112

answers:

3

Some of the new features of Perl 5.10 and 5.12, such as "say", are defined as features, that you can enable or disallow explicitly using the "feature" pragma. But other additions, like the named capture groups of regexes, are implicit.

When I write Perl using a 5.10+ interpreter, but want it to also run on 5.8, can I make Perl complain about using anything that's not in 5.8? Obviously, it is good practice to test your code on all major versions you intend it to run on, but it'd still be nice to have Perl warn me automatically.

+4  A: 

I don't think you can make Perl check as you run the code, but check out Perl::MinimumVersion and Test::MinimumVersion. (The latter is just a Test::Builder wrapper around the former.)

cjm
Do you have something where this works? I don't think it will help.
brian d foy
Well, I've never tried it myself, but this is the problem that it's attempting to solve. How well it solves it is another question.
cjm
+6  A: 

When I want to ensure that a program will run under particular versions of perl, I test it under that version of perl. A feature of my release application tests under multiple perls before it actually uploads.

This requires that you have a proper test suite and write enough tests. It's easy to maintain several separate perl installations at the same time, too, as I show in Effective Perl Programming.

Test::MinimumVersion almost sounds like it might work, but it has several limitations. It only looks at the file you give it (so it will not check anything you load), and I don't think it actually looks inside regex patterns. Each of these report that the minimum version is 5.004, which is not true for any of them:

#!perl

use Perl::MinimumVersion;

my $p_flag = <<'SOURCE';
'123' =~ m/[123]/p; # 5.10 feature
SOURCE

my $named_capture = <<'SOURCE';
'123' =~ m/(?<num>[123])/; # 5.10 feature
SOURCE

my $r_line_ending = <<'SOURCE';
'123' =~ m/[123]\R/p; # 5.12 feature
SOURCE

my $say = <<'SOURCE';
say 'Hello';
SOURCE

my $smart_match = <<'SOURCE';
$boolean = '123' ~~ @array;
SOURCE

my $given = <<'SOURCE';
given( $foo ) {
    when( /123/ ) { say 'Hello' }
    };

SOURCE

foreach my $source ( $p_flag, $named_capture, $r_line_ending, $say, $smart_match, $given ) {
    print "----Source---\n$source\n-----";
    my $version = Perl::MinimumVersion->new( \$source  )->minimum_version;
    print "Min version is $version\n";
    }

Part of the reason Perl::MinimumVersion works is because it looks for hints that the source gives it already, such as use 5.010, and use feature so on. However, that's not the only way to enable features. And, as you'll note, it misses things like the /p flag, at least until someone adds a check for that. However, you'll always be chasing things like that with a PPI solution.

It's easier just to compile it, run the tests, and find out.

brian d foy
Thanks for the amazingly in-depth answer (as usual). Our problem is, like so often, tons of old code without tests. Nevertheless I see that your answer is the right one, accepted.
Thomas Kappler
"say" can be added by Perl6::Say 9(I use it myself when on 5.8.8) - so I don't plan to add check for this in Perl::MinimumVersion. Regexes are too hard to add, but "given" and "when" should be added.
Alexandr Ciornii
I should note that the problem isn't really with Perl::MinimumVersion, but the idea of static analysis in Perl. PPI is wonderful, but our ability to understand what it parsed is fundamentally problematic because Perl is special. :)
brian d foy
+2  A: 

Well from reading other answers your answer is no, but perhaps App::perlbrew can help you install and manage multiple versions of perl for testing.

xenoterracide