package constant;
-use 5.005;
+use 5.008;
use strict;
use warnings::register;
use vars qw($VERSION %declared);
-$VERSION = '1.21';
+$VERSION = '1.31';
#=======================================================================
my %forbidden = (%keywords, %forced_into_main);
-my $str_end = $] >= 5.006 ? "\\z" : "\\Z";
-my $normal_constant_name = qr/^_?[^\W_0-9]\w*$str_end/;
-my $tolerable = qr/^[A-Za-z_]\w*$str_end/;
-my $boolean = qr/^[01]?$str_end/;
+my $normal_constant_name = qr/^_?[^\W_0-9]\w*\z/;
+my $tolerable = qr/^[A-Za-z_]\w*\z/;
+my $boolean = qr/^[01]?\z/;
BEGIN {
# We'd like to do use constant _CAN_PCS => $] > 5.009002
# but that's a bit tricky before we load the constant module :-)
# By doing this, we save 1 run time check for *every* call to import.
- no strict 'refs';
my $const = $] > 5.009002;
- *_CAN_PCS = sub () {$const};
+ my $downgrade = $] < 5.015004; # && $] >= 5.008
+ my $constarray = exists &_make_const;
+ if ($const) {
+ Internals::SvREADONLY($const, 1);
+ Internals::SvREADONLY($downgrade, 1);
+ $constant::{_CAN_PCS} = \$const;
+ $constant::{_DOWNGRADE} = \$downgrade;
+ $constant::{_CAN_PCS_FOR_ARRAY} = \$constarray;
+ }
+ else {
+ no strict 'refs';
+ *{"_CAN_PCS"} = sub () {$const};
+ *{"_DOWNGRADE"} = sub () { $downgrade };
+ *{"_CAN_PCS_FOR_ARRAY"} = sub () { $constarray };
+ }
}
#=======================================================================
if ($multiple || @_ == 1) {
my $scalar = $multiple ? $constants->{$name} : $_[0];
- # Work around perl bug #xxxxx: Sub names (actually glob
- # names in general) ignore the UTF8 flag. So we have to
- # turn it off to get the "right" symbol table entry.
- utf8::is_utf8 $name and utf8::encode $name;
+ if (_DOWNGRADE) { # for 5.8 to 5.14
+ # Work around perl bug #31991: Sub names (actually glob
+ # names in general) ignore the UTF8 flag. So we have to
+ # turn it off to get the "right" symbol table entry.
+ utf8::is_utf8 $name and utf8::encode $name;
+ }
# The constant serves to optimise this entire block out on
# 5.8 and earlier.
- if (_CAN_PCS && $symtab && !exists $symtab->{$name}) {
- # No typeglob yet, so we can use a reference as space-
- # efficient proxy for a constant subroutine
+ if (_CAN_PCS) {
+ # Use a reference as a proxy for a constant subroutine.
+ # If this is not a glob yet, it saves space. If it is
+ # a glob, we must still create it this way to get the
+ # right internal flags set, as constants are distinct
+ # from subroutines created with sub(){...}.
# The check in Perl_ck_rvconst knows that inlinable
# constants from cv_const_sv are read only. So we have to:
Internals::SvREADONLY($scalar, 1);
- $symtab->{$name} = \$scalar;
- ++$flush_mro;
+ if ($symtab && !exists $symtab->{$name}) {
+ $symtab->{$name} = \$scalar;
+ ++$flush_mro;
+ }
+ else {
+ local $constant::{_dummy} = \$scalar;
+ *$full_name = \&{"_dummy"};
+ }
} else {
*$full_name = sub () { $scalar };
}
} elsif (@_) {
my @list = @_;
- *$full_name = sub () { @list };
+ if (_CAN_PCS_FOR_ARRAY) {
+ _make_const($list[$_]) for 0..$#list;
+ _make_const(@list);
+ if ($symtab && !exists $symtab->{$name}) {
+ $symtab->{$name} = \@list;
+ $flush_mro++;
+ }
+ else {
+ local $constant::{_dummy} = \@list;
+ *$full_name = \&{"_dummy"};
+ }
+ }
+ else { *$full_name = sub () { @list }; }
} else {
*$full_name = sub () { };
}
When you declare a constant such as C<PI> using the method shown
above, each machine your script runs upon can have as many digits
-of accuracy as it can use. Also, your program will be easier to
+of accuracy as it can use. Also, your program will be easier to
read, more likely to be maintained (and maintained correctly), and
far less likely to send a space probe to the wrong planet because
nobody noticed the one equation in which you wrote C<3.14195>.
=head1 NOTES
As with all C<use> directives, defining a constant happens at
-compile time. Thus, it's probably not correct to put a constant
+compile time. Thus, it's probably not correct to put a constant
declaration inside of a conditional statement (like C<if ($foo)
{ use constant ... }>).
The use of all caps for constant names is merely a convention,
although it is recommended in order to make constants stand out
and to help avoid collisions with other barewords, keywords, and
-subroutine names. Constant names must begin with a letter or
-underscore. Names beginning with a double underscore are reserved. Some
+subroutine names. Constant names must begin with a letter or
+underscore. Names beginning with a double underscore are reserved. Some
poor choices for names will generate warnings, if warnings are enabled at
compile time.
=head1 TECHNICAL NOTES
In the current implementation, scalar constants are actually
-inlinable subroutines. As of version 5.004 of Perl, the appropriate
+inlinable subroutines. As of version 5.004 of Perl, the appropriate
scalar constant is inserted directly in place of some subroutine
-calls, thereby saving the overhead of a subroutine call. See
+calls, thereby saving the overhead of a subroutine call. See
L<perlsub/"Constant Functions"> for details about how and when this
happens.
In the rare case in which you need to discover at run time whether a
particular constant has been declared via this module, you may use
-this function to examine the hash C<%constant::declared>. If the given
+this function to examine the hash C<%constant::declared>. If the given
constant name does not include a package name, the current package is
used.
=head1 CAVEATS
-In the current version of Perl, list constants are not inlined
-and some symbols may be redefined without generating a warning.
+List constants are not inlined unless you are using Perl v5.20 or higher.
+In v5.20 or higher, they are still not read-only, but that may change in
+future versions.
It is not possible to have a subroutine or a keyword with the same
-name as a constant in the same package. This is probably a Good Thing.
+name as a constant in the same package. This is probably a Good Thing.
A constant with a name in the list C<STDIN STDOUT STDERR ARGV ARGVOUT
ENV INC SIG> is not allowed anywhere but in package C<main::>, for
L<Readonly> - Facility for creating read-only scalars, arrays, hashes.
-L<Const> - Facility for creating read-only variables. Similar to C<Readonly>,
-but uses C<SvREADONLY> instead of C<tie>.
-
L<Attribute::Constant> - Make read-only variables via attribute
L<Scalar::Readonly> - Perl extension to the C<SvREADONLY> scalar flag