1ReadonlyX(3pm)        User Contributed Perl Documentation       ReadonlyX(3pm)
2
3
4

NAME

6       ReadonlyX - Faster facility for creating read-only scalars, arrays,
7       hashes
8

Synopsis

10           use strict;
11           use warnings;
12           use ReadonlyX;
13
14           # Read-only scalar
15           my $sca1;
16           Readonly::Scalar $sca1    => 3.14;
17           Readonly::Scalar my $sca2 => time;
18           Readonly::Scalar my $sca3 => 'Welcome';
19           my $sca4 = time();
20           Readonly::Scalar $sca4; # Value is not clobbered
21
22           # Read-only array
23           my @arr1;
24           Readonly::Array @arr1 => [1 .. 4];
25
26           # or:
27           Readonly::Array my @arr2 => (1, 3, 5, 7, 9);
28
29           # Read-only hash
30           my %hash1;
31           Readonly::Hash %hash1    => (key => 'value', key2 => 'value');
32           Readonly::Hash my %hash2 => (key => 'value', key2 => 'value');
33
34           # or:
35           Readonly::Hash my %hash3 => {key => 'value', key2 => 'value'};
36
37           # You can use the read-only variables like any regular variables:
38           print $sca1;
39           my $something = $sca1 + $arr1[2];
40           warn 'Blah!' if $hash1{key2};
41
42           # But if you try to modify a value, your program will die:
43           $sca2 = 7;           # "Modification of a read-only value attempted"
44           push @arr1, 'seven'; # "Modification of a read-only value attempted"
45           $arr1[1] = 'nine';   # "Modification of a read-only value attempted"
46           delete $hash1{key};  # Attempt to delete readonly key 'key' from a restricted hash
47
48           # Create mutable clones
49           Readonly::Scalar $scalar => {qw[this that]};
50           # $scalar->{'eh'} = 'foo'; # Modification of a read-only value attempted
51           my $scalar_clone = Readonly::Clone $scalar;
52           $scalar_clone->{'eh'} = 'foo';
53           # $scalar_clone is now {this => 'that', eh => 'foo'};
54

Description

56       This is a near-drop-in replacement for Readonly, the popular facility
57       for creating non-modifiable variables. This is useful for configuration
58       files, headers, etc. It can also be useful as a development and
59       debugging tool for catching updates to variables that should not be
60       changed.
61
62       If you really need to have immutable variables in new code, use this
63       instead of Readonly. You'll thank me later. See the section entitled
64       "ReadonlyX vs. Readonly" for more.
65

Functions

67       All of these functions can be imported into your package by name.
68
69   Readonly::Scalar
70           Readonly::Scalar $pi      => 3.14;
71           Readonly::Scalar my $aref => [qw[this that]]; # list ref
72           Readonly::Scalar my $href => {qw[this that]}; # hash ref
73
74       Creates a non-modifiable scalar and assigns a value of to it.
75       Thereafter, its value may not be changed. Any attempt to modify the
76       value will cause your program to die.
77
78       If the given value is a reference to a scalar, array, or hash, then
79       this function will mark the scalar, array, or hash it points to as
80       being readonly as well, and it will recursively traverse the structure,
81       marking the whole thing as readonly.
82
83       If the variable is already readonly, the program will die with an error
84       about reassigning readonly variables.
85
86   Readonly::Array
87           Readonly::Array @arr1    => [1 .. 4];
88           Readonly::Array my @arr2 => (1, 3, 5, 7, 9);
89
90       Creates a non-modifiable array and assigns the specified list of values
91       to it.  Thereafter, none of its values may be changed; the array may
92       not be lengthened or shortened. Any attempt to do so will cause your
93       program to die.
94
95       If any of the values passed is a reference to a scalar, array, or hash,
96       then this function will mark the scalar, array, or hash it points to as
97       being Readonly as well, and it will recursively traverse the structure,
98       marking the whole thing as Readonly.
99
100       If the variable is already readonly, the program will die with an error
101       about reassigning readonly variables.
102
103   Readonly::Hash
104           Readonly::Hash %h => (key => 'value', key2 => 'value');
105           Readonly::Hash %h => {key => 'value', key2 => 'value'};
106
107       Creates a non-modifiable hash and assigns the specified keys and values
108       to it.  Thereafter, its keys or values may not be changed. Any attempt
109       to do so will cause your program to die.
110
111       A list of keys and values may be specified (with parentheses in the
112       synopsis above), or a hash reference may be specified (curly braces in
113       the synopsis above). If a list is specified, it must have an even
114       number of elements, or the function will die.
115
116       If any of the values is a reference to a scalar, array, or hash, then
117       this function will mark the scalar, array, or hash it points to as
118       being Readonly as well, and it will recursively traverse the structure,
119       marking the whole thing as Readonly.
120
121       If the variable is already readonly, the program will die with an error
122       about reassigning readonly variables.
123
124   Readonly::Clone
125           my $scalar_clone = Readonly::Clone $scalar;
126
127       When cloning using Storable or Clone you will notice that the value
128       stays readonly, which is correct. If you want to clone the value
129       without copying the readonly flag, use this.
130
131           Readonly::Scalar my $scalar => {qw[this that]};
132           # $scalar->{'eh'} = 'foo'; # Modification of a read-only value attempted
133           my $scalar_clone = Readonly::Clone $scalar;
134           $scalar_clone->{'eh'} = 'foo';
135           # $scalar_clone is now {this => 'that', eh => 'foo'};
136
137       In this example, the new variable ($scalar_clone) is a mutable clone of
138       the original $scalar. You can change it like any other variable.
139

Examples

141       Here are a few very simple examples again to get you started:
142
143   Scalars
144       A plain old read-only value:
145
146           Readonly::Scalar $a => "A string value";
147
148       The value need not be a compile-time constant:
149
150           Readonly::Scalar $a => $computed_value;
151
152       Need an undef constant? Okay:
153
154           Readonly::Scalar $a;
155
156   Arrays/Lists
157       A read-only array:
158
159           Readonly::Array @a => (1, 2, 3, 4);
160
161       The parentheses are optional:
162
163           Readonly::Array @a => 1, 2, 3, 4;
164
165       You can use Perl's built-in array quoting syntax:
166
167           Readonly::Array @a => qw[1 2 3 4];
168
169       You can initialize a read-only array from a variable one:
170
171           Readonly::Array @a => @computed_values;
172
173       A read-only array can be empty, too:
174
175           Readonly::Array @a => ();
176           # or
177           Readonly::Array @a;
178
179   Hashes
180       Typical usage:
181
182           Readonly::Hash %a => (key1 => 'value1', key2 => 'value2');
183           # or
184           Readonly::Hash %a => {key1 => 'value1', key2 => 'value2'};
185
186       A read-only hash can be initialized from a variable one:
187
188           Readonly::Hash %a => %computed_values;
189
190       A read-only hash can be empty:
191
192           Readonly::Hash %a => ();
193           # or
194           Readonly::Hash %a;
195
196       If you pass an odd number of values, the program will die:
197
198           Readonly::Hash my %a => (key1 => 'value1', "value2");
199           # This dies with "Odd number of elements in hash assignment"
200

ReadonlyX vs. Readonly

202       The original Readonly module was written nearly twenty years ago when
203       the built-in capability to lock variables didn't exist in perl's core.
204       The original author came up with the amazingly brilliant idea to use
205       the new (at the time) tie(...) construct. It worked amazingly well! But
206       it wasn't long before the speed penalty of tied varibles became
207       embarrassingly obvious. Check any review of Readonly written before
208       2013; the main complaint was how slow it was and the benchmarks proved
209       it.
210
211       In an equally brilliant move to work around tie, Readonly::XS was
212       released for perl 5.8.9 and above. This bypassed tie(...) for basic
213       scalars which made a huge difference.
214
215       During all this, two very distinct APIs were also designed and
216       supported by Readonly. One for (then) modern perl and one written for
217       perl 5.6. To make this happen, time consuming eval operations were
218       required and the codebase grew so complex that fixing bugs was nearly
219       impossible. Readonly was three different modules all with different
220       sets of quirks and bugs to fix depending on what version of perl and
221       what other modules you had installed. It was a mess.
222
223       So, after the original author abandoned both Readonly and Readonly::XS,
224       as bugs were found, they went unfixed. The combination of speed and
225       lack of development spawned several similar modules which usually did a
226       better job but none were a total drop-in replacement.
227
228       Until now.
229
230       ReadonlyX is the best of recent versions of Readonly without the old
231       API and without the speed penalty of tie(...). It's what I'd like to do
232       with Readonly if resolving bugs in it wouldn't break 16 years of code
233       out there in Darkpan.
234
235       In short, unlike Readonly, ReadonlyX...
236
237       ...does not use slow tie(...) magic or eval. There shouldn't be a speed
238       penalty after making the structure immutable. See the Benchmarks
239       section below
240       ...does not strive to work on perl versions I can't even find a working
241       build of to test against
242       ...has a single, clean API! What do all of these different forms of the
243       original Readonly API do?
244               use Readonly;
245               Readonly  my @array1        => [2];
246               Readonly \my @array2        => [2];
247               Readonly::Array  my @array3 => [2];
248               Readonly::Array1 my @array4 => [2];
249
250           Be careful because they all behave very differently. Even your
251           version of perl and the contents of the list changes how they work.
252           Give up? Yeah, me too.  Bonus: Guess which one doesn't actually
253           make the list items read only.
254
255       ...does the right thing when it comes to deep vs. shallow structures
256       ...allows implicit undef values for scalars (Readonly inconsistantly
257       allows this for hashes and arrays but not scalars)
258       ...a lot more I can't think of right now but will add when they come to
259       me
260       ...is around 100 lines instead of 460ish so maintaining it will be a
261       breeze
262       ...doesn't clobber predefined variables when making them readonly
263           Using Readonly, this:
264
265               my @array = qw[very important stuff];
266               Readonly::Array @array;
267               print "@array";
268
269           ...wouldn't print anything. I consider it a bug but I'm not sure
270           why it was designed this way originally. With ReadonlyX, you won't
271           lose your 'very important stuff'.
272
273           Note that this is an incompatible change! If you attempt to do this
274           and then switch to plain 'ol Readonly, your code will not work.
275

Benchmarks

277       Don't believe Readonly is slow? Here's the result of basic
278       benchmarking:
279
280           Hash Benchmark: timing 5000000 iterations of const, normal, readonly, readonlyx...
281                const:  3 wallclock secs ( 2.73 usr +  0.02 sys =  2.75 CPU) @ 1818181.82/s (n=5000000)
282               normal:  3 wallclock secs ( 3.02 usr + -0.02 sys =  3.00 CPU) @ 1666666.67/s (n=5000000)
283             readonly: 47 wallclock secs (40.64 usr +  0.03 sys = 40.67 CPU) @ 122931.67/s (n=5000000)
284            readonlyx:  4 wallclock secs ( 3.22 usr + -0.01 sys =  3.20 CPU) @ 1560549.31/s (n=5000000)
285           Array Benchmark: timing 5000000 iterations of const, normal, readonly, readonlyx...
286                const:  3 wallclock secs ( 2.19 usr +  0.03 sys =  2.22 CPU) @ 2253267.24/s (n=5000000)
287               normal:  1 wallclock secs ( 1.44 usr +  0.00 sys =  1.44 CPU) @ 3474635.16/s (n=5000000)
288             readonly: 36 wallclock secs (32.52 usr +  0.13 sys = 32.64 CPU) @ 153181.58/s (n=5000000)
289            readonlyx:  1 wallclock secs ( 1.12 usr + -0.02 sys =  1.11 CPU) @ 4512635.38/s (n=5000000)
290           Scalar Benchmark: timing 5000000 iterations of const, normal, readonly, readonlyx...
291                const:  1 wallclock secs ( 1.14 usr + -0.02 sys =  1.12 CPU) @ 4448398.58/s (n=5000000)
292               normal:  1 wallclock secs ( 0.99 usr +  0.02 sys =  1.00 CPU) @ 4995005.00/s (n=5000000)
293             readonly:  1 wallclock secs ( 1.25 usr +  0.00 sys =  1.25 CPU) @ 4000000.00/s (n=5000000)
294            readonlyx:  2 wallclock secs ( 1.20 usr +  0.00 sys =  1.20 CPU) @ 4156275.98/s (n=5000000)
295
296       Find the script to run them yourself in "eg/benchmark.pl".
297

Requirements

299       There are no non-core requirements.
300

Bug Reports

302       If email is better for you, my address is mentioned below but I would
303       rather have bugs sent through the issue tracker found at
304       http://github.com/sanko/readonly/issues.
305
306       ReadonlyX can be found is the branch of Readonly found here:
307       https://github.com/sanko/readonly/tree/ReadonlyX
308

Author

310       Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/
311
312       CPAN ID: SANKO
313
315       Copyright (C) 2016 by Sanko Robinson <sanko@cpan.org>
316
317       This module is free software; you can redistribute it and/or modify it
318       under the same terms as Perl itself.
319
320
321
322perl v5.36.0                      2023-01-20                    ReadonlyX(3pm)
Impressum