| Perl-Critic-Pulp documentation | view source | Contained in the Perl-Critic-Pulp distribution. |
Perl::Critic::Policy::Compatibility::ConstantLeadingUnderscore - new enough "constant" module for leading underscores
This policy is part of the Perl::Critic::Pulp|Perl::Critic::Pulp
addon. It asks that if you have a constant with a leading underscore,
use constant _FOO ... # leading underscore on name
then you explicitly declare use 5.6 or use constant 1.02, or higher,
since constant.pm before that did not allow leading underscores.
use constant _FOO => 123; # bad
use 5.006;
use constant _FOO => 123; # ok
use constant 1.02;
use constant _FOO => 123; # ok
use constant 1.02 _FOO => 123; # ok
The idea is to avoid trouble in code which might run on Perl 5.005, or might in principle still run there. On that basis this policy is under the "compatibility" theme (see POLICY THEMES in Perl::Critic).
Asking for the new enough module use constant 1.02 is suggested, since
it's the module feature which is required and the code might then still run
on Perl 5.005 or earlier if the user has a suitable constant.pm from
CPAN.
A version declaration must be before the first leading underscore, so it's checked before the underscore is attempted (and gives an error).
use constant _FOO => 123; # bad
use 5.006;
A require for the Perl version is not enough since the use constant is
at BEGIN time, before plain code.
require 5.006; # doesn't run early enough
use constant _FOO => 123; # bad
But a require within a BEGIN block is ok (an older style, still found
occasionally).
BEGIN { require 5.006 }
use constant _FOO => 123; # ok
BEGIN {
require 5.006;
and_other_setups ...;
}
use constant _FOO => 123; # ok
Currently ConstantLeadingUnderscore pays no attention to any conditionals
within the BEGIN, it assumes any require there always runs. It might
be tricked by obscure tests but hopefully anything like that is rare.
A quoted version number like
use constant '1.02'; # no good
is no good, only a bare number is recognised by the use statement.
A string like that in fact goes through to constant as a name to define
(which it will reject).
Leading underscores in the multi-constant hash are not flagged, since if you've got multi-constants then you've got underscores. See Compatibility::ConstantPragmaHash for checking multi-constants.
use constant { _FOO => 1 }; # not checked
Leading double-underscore is disallowed by all versions of constant.pm.
That's not reported by this policy since the code won't run at all.
use constant __FOO = 123; # not allowed by any constant.pm
Explicitly adding required version numbers in the code can be irritating, especially if other things you're using only run on 5.6 up anyway. But declaring what code needs is accurate, it allows maybe for backports of modules, and explicit versions can be grepped out to create or check Makefile.PL or Build.PL prereqs.
As always if you don't care about this and in particular if you only ever
use Perl 5.6 anyway then you can disable ConstantLeadingUnderscore from
your .perlcriticrc in the usual way (see
CONFIGURATION in Perl::Critic),
[-Compatibility::ConstantLeadingUnderscore]
It's easy to write your own constant subr and it can have any name at all
(anything acceptable to Perl), bypassing the sanity checks or restrictions
in constant.pm. Only the () prototype is a bit obscure.
sub _FOO () { return 123 }
The key benefit of subs like this, whether from constant.pm or
explicitly, is that the value is inlined and can be constant-folded in an
arithmetic expression etc (see Constant Functions in perlsub).
print 2*_FOO; # folded to 246 at compile-time
The purpose of a leading underscore is normally a hint that the sub is meant
to be private to the module and/or its friends. If you don't need the
constant folding then a my scalar is even more private, being invisible
to anything outside the relevant scope,
my $FOO = 123; # more private
# ...
do_something ($FOO); # nothing to constant-fold anyway
The scalar from a constant sub is flagged read-only, which might prevent
accidental when passed around. The Readonly module can have a similar
effect on scalars. If you've got Readonly::XS then it's just a flag too
(no performance penalty on using the value).
use Readonly;
Readonly::Scalar my $FOO => 123;
Perl::Critic::Pulp, Perl::Critic, Perl::Critic::Policy::Compatibility::ConstantPragmaHash, Perl::Critic::Policy::ValuesAndExpressions::ProhibitConstantPragma, Perl::Critic::Policy::Modules::RequirePerlVersion
Constant Functions in perlsub
http://user42.tuxfamily.org/perl-critic-pulp/index.html
Copyright 2008, 2009, 2010, 2011 Kevin Ryde
Perl-Critic-Pulp is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version.
Perl-Critic-Pulp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with Perl-Critic-Pulp. If not, see <http://www.gnu.org/licenses/>.
| Perl-Critic-Pulp documentation | view source | Contained in the Perl-Critic-Pulp distribution. |