package constant;
-
+use 5.005;
use strict;
-use 5.006_00;
use warnings::register;
-our($VERSION, %declared);
-$VERSION = '1.04';
+use vars qw($VERSION %declared);
+$VERSION = '1.17';
#=======================================================================
# Some names are evil choices.
my %keywords = map +($_, 1), qw{ BEGIN INIT CHECK END DESTROY AUTOLOAD };
+$keywords{UNITCHECK}++ if $] > 5.009;
my %forced_into_main = map +($_, 1),
qw{ STDIN STDOUT STDERR ARGV ARGVOUT ENV INC SIG };
sub import {
my $class = shift;
return unless @_; # Ignore 'use constant;'
- my %constants = ();
+ my $constants;
my $multiple = ref $_[0];
+ my $pkg = caller;
+ my $symtab;
+ my $str_end = $] >= 5.006 ? "\\z" : "\\Z";
+
+ if ($] > 5.009002) {
+ no strict 'refs';
+ $symtab = \%{$pkg . '::'};
+ };
if ( $multiple ) {
if (ref $_[0] ne 'HASH') {
require Carp;
Carp::croak("Invalid reference type '".ref(shift)."' not 'HASH'");
}
- %constants = %{+shift};
+ $constants = shift;
} else {
- $constants{+shift} = undef;
+ $constants->{+shift} = undef;
}
- foreach my $name ( keys %constants ) {
+ foreach my $name ( keys %$constants ) {
unless (defined $name) {
require Carp;
Carp::croak("Can't use undef as constant name");
}
- my $pkg = caller;
# Normal constant name
- if ($name =~ /^_?[^\W_0-9]\w*\z/ and !$forbidden{$name}) {
+ if ($name =~ /^_?[^\W_0-9]\w*$str_end/ and !$forbidden{$name}) {
# Everything is okay
# Name forced into main, but we're not in main. Fatal.
Carp::croak("Constant name '$name' begins with '__'");
# Maybe the name is tolerable
- } elsif ($name =~ /^[A-Za-z_]\w*\z/) {
+ } elsif ($name =~ /^[A-Za-z_]\w*$str_end/) {
# Then we'll warn only if you've asked for warnings
if (warnings::enabled()) {
if ($keywords{$name}) {
} elsif ($forced_into_main{$name}) {
warnings::warn("Constant name '$name' is " .
"forced into package main::");
- } else {
- # Catch-all - what did I miss? If you get this error,
- # please let me know what your constant's name was.
- # Write to <rootbeer@redcat.com>. Thanks!
- warnings::warn("Constant name '$name' has unknown problems");
}
}
# Looks like a boolean
# use constant FRED == fred;
- } elsif ($name =~ /^[01]?\z/) {
+ } elsif ($name =~ /^[01]?$str_end/) {
require Carp;
if (@_) {
Carp::croak("Constant name '$name' is invalid");
no strict 'refs';
my $full_name = "${pkg}::$name";
$declared{$full_name}++;
- if ($multiple) {
- my $scalar = $constants{$name};
- *$full_name = sub () { $scalar };
- } else {
- if (@_ == 1) {
- my $scalar = $_[0];
- *$full_name = sub () { $scalar };
- } elsif (@_) {
- my @list = @_;
- *$full_name = sub () { @list };
+ if ($multiple || @_ == 1) {
+ my $scalar = $multiple ? $constants->{$name} : $_[0];
+ if ($symtab && !exists $symtab->{$name}) {
+ # No typeglob yet, so we can use a reference as space-
+ # efficient proxy for a constant subroutine
+ # 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;
+ mro::method_changed_in($pkg);
} else {
- *$full_name = sub () { };
+ *$full_name = sub () { $scalar };
}
+ } elsif (@_) {
+ my @list = @_;
+ *$full_name = sub () { @list };
+ } else {
+ *$full_name = sub () { };
}
}
}
=head1 DESCRIPTION
-This will declare a symbol to be a constant with the given value.
+This pragma allows you to declare constants at compile-time.
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
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>.
-When a constant is used in an expression, perl replaces it with its
+When a constant is used in an expression, Perl replaces it with its
value at compile time, and may then optimize the expression further.
In particular, any code in an C<if (CONSTANT)> block will be optimized
away if the constant is false.
use constant TIMESTAMP => scalar localtime; # right
The first line above defines C<TIMESTAMP> as a 9-element list, as
-returned by localtime() in list context. To set it to the string
-returned by localtime() in scalar context, an explicit C<scalar>
+returned by C<localtime()> in list context. To set it to the string
+returned by C<localtime()> in scalar context, an explicit C<scalar>
keyword is required.
List constants are lists, not arrays. To index or slice them, they
$constant::declared{$full_name};
}
-=head1 BUGS
+=head1 CAVEATS
In the current version of Perl, list constants are not inlined
and some symbols may be redefined without generating a warning.
(or simply use a comma in place of the big arrow) instead of
C<< CONSTANT => 'value' >>.
-=head1 AUTHOR
+=head1 SEE ALSO
+
+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
+
+L<Hash::Util> - A selection of general-utility hash subroutines (mostly
+to lock/unlock keys and values)
+
+=head1 BUGS
+
+Please report any bugs or feature requests via the perlbug(1) utility.
+
+=head1 AUTHORS
Tom Phoenix, E<lt>F<rootbeer@redcat.com>E<gt>, with help from
many other folks.
Documentation mostly rewritten by Ilmari Karonen,
E<lt>F<perl@itz.pp.sci.fi>E<gt>.
-=head1 COPYRIGHT
+This program is maintained by the Perl 5 Porters.
+The CPAN distribution is maintained by SE<eacute>bastien Aperghis-Tramoni
+E<lt>F<sebastien@aperghis.net>E<gt>.
+
+=head1 COPYRIGHT & LICENSE
Copyright (C) 1997, 1999 Tom Phoenix