Modules · Language · 1.04
Const::XS
Read-only scalars, arrays and hashes, all the way down, in XS.
const my %config => (...) sets a variable and makes it read-only, with every array and hash inside it. A key that was never set is an error rather than a quiet undef, so a typo in a constant's name fails where it is made.
use Const::XS qw(const);
const my %config => (
workers => 5,
hosts => [qw(a.example b.example)],
retry => { times => 3, wait => 2 },
);
print $config{retry}{times}, "\n"; # 3
# read-only all the way down: the nested array and hash too
eval { push @{ $config{hosts} }, 'c.example' };
print "refused: $@"; # Modification of a read-only value attempted
eval { $config{retry}{times} = 10 };
print "refused: $@";
# and a key that was never set is an error, not a quiet undef
eval { my $port = $config{port} };
print "refused: $@"; # Attempt to access disallowed key 'port'
print exists $config{port} ? '' : "no port\n"; # exists still asks safely
What you get
-
Deeply read-only
An array or hash made with
constis read-only, and so is every array and hash inside it. A push, a store or a delete anywhere in the structure dies. -
Missing keys are errors
Reading a key a constant hash does not have dies, naming the key, and
existsstill asks safely. A misspelt constant fails where it is used, not three calls later. -
Any variable, after the fact
make_readonlylocks a variable that already exists,unmake_readonlyopens it again, andis_readonlysays which it is. -
A read-only copy
make_readonly_refreturns a read-only copy of a structure in a variable that can still be rebound. -
Shared between packages
Declare
const ourvalues in one package and export them, so every module reads the same values and none of them can change one.
In use
use Const::XS qw(make_readonly unmake_readonly is_readonly make_readonly_ref);
# an existing variable, made read-only in place, and back again
my %limits = (upload => 1_048_576, requests => 100);
make_readonly(%limits);
print is_readonly(%limits) ? "locked\n" : "open\n"; # locked
unmake_readonly(%limits);
$limits{requests} = 200;
print "requests: $limits{requests}\n"; # 200
# a read-only copy of a structure, in a variable that can still be rebound
my $defaults = make_readonly_ref({ theme => 'dark', lang => 'en' });
eval { $defaults->{theme} = 'light' };
print $@ ? "the copy is read-only\n" : '';
$defaults = { theme => 'light' }; # the variable itself is not
print "$defaults->{theme}\n"; # light
Measured in its POD
One run, as the POD records it, with no machine named: making a read-only string, hash and array and reading them back. Const::XS did 1,275,510 a second, Const::PP 254,194, Const::Fast 221,828 and Readonly 143,720, so Const::XS was 5.8 times Const::Fast and 8.9 times Readonly.