Perl has changed a lot over the years and it can be hard to keep track of what was introduced when and how to enable it in your project. Additionally some new features get back ported via external modules. Usually in a project you want a consistent feature setup across all the modules comprising it. Also you want an easy way to enable new stuff when it comes out and you are able to upgrade.
There's probably several ways to do this but here's the approach I take. I create a '::Syntax' module in the root of my project namespace and use that to setup all the features I want. For example, let's say I have a project "Example". I create a module like so:
package Example::Syntax;
use strict;
use warnings;
use Import::Into;
use Module::Runtime;
sub importables {
my ($class) = @_;
return (
'utf8',
'strict',
'warnings',
['feature', ':5.16'],
['experimental', 'signatures', 'postderef'],
);
}
sub import {
my ($class, @args) = @_;
my $caller = caller;
foreach my $import_proto($class->importables) {
my ($module, @args) = (ref($import_proto)||'') eq 'ARRAY' ?
@$import_proto : ($import_proto, ());
Module::Runtime::use_module($module)
->import::into($caller, @args)
}
}
1;
I can then use this in all my projects modules:
package Example::User;
use Example::Syntax;
# Rest of code.
Using 'Example::Syntax' this way is the same as:
package Example::User;
use utf8;
use strict;
use warnings;
use feature ':5.16';
use experimental 'signatures', 'postderef';
# Rest of code.
Later on if you upgrade to a new version of Perl you can just tweak syntax file. For example if you move to Perl 5.38 then signatures are no longer loaded via the experimental pragma. All your projects code will just continue to work correctly.
Although the Perl team goes to a lot of trouble to try and make sure stuff doesn't break across versions there's no reason to not add a bit of extra safety by centralizing your feature setup. Otherwise you might find yourself with a tedious job of having to tweak boilerplate across your projects. Personally I think this approach makes things a bit neater as well, or fewer lines at least.
A quick last note...
It might come to some that you could use this approach to preload some handy modules, like things out of Scalar::Utils for example. I recommend not going crazy here and creating a default setup that might be surprising to newcomers to your project. A light touch is probably best.
Top comments (6)
Thanks both, yes I meant perl-5.10.1 as we have some legacy code running with mod_perl 1 and 5.10.1 was the latest perl I could get to compile with it.
We nearly have it replaced with PSGI and then we can move to latest perl.
In the meantime, I am interested in ways we can simplify common headers and make code work across perl 5.10.1 (legacy mod_perl), 5.16.3 (ships with RedHat 7) and perl-5.38.0 (latest).
I did some testing @jjn1056 and found your approach works fine with perl 5.10.1, 5.16.3 and perl 5.34.0. I trimmed down the feature imports to what would work on 5.10.
testing on RHEL 7
Looks great, let me know if you need a consultant to help on the PSGI migration, I've done modPerl 1 to PSGI before :). Sounds like you're well on the way but if you get stuck you know where to find me
Nice one. Is there a minimum perl version needed for this, e.g. 10.1?
Import::Into and Module::Runtime seems to run on v5.6.0 (!!!) without trouble (you can check CPAN testers if you don't believe me) so you should be able to use my Syntax pragma as a template, however if you are on that old a Perl you won't have too many modern features to enable. That said there's modules on CPAN that try to shoehorn in more modern features that could be enabled using a pragma like this one.
5.something surely? Or 5.10.1? The article is about modern Perl so I'd say 5.34 onwards.
perl 5.10 is fairly puny when it comes to features :-)
From perldoc.perl.org/feature#FEATURE-B...
:5.10 bareword_filehandles indirect
multidimensional say state switch