1ReadonlyX(3pm) User Contributed Perl Documentation ReadonlyX(3pm)
2
3
4
6 ReadonlyX - Faster facility for creating read-only scalars, arrays,
7 hashes
8
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
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
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
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
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
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
299 There are no non-core requirements.
300
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
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)