Filename | /usr/share/perl5/Readonly.pm |
Statements | Executed 30 statements in 2.15ms |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
---|---|---|---|---|---|
1 | 1 | 1 | 38µs | 38µs | BEGIN@96 | Readonly::Array::
1 | 1 | 1 | 24µs | 24µs | BEGIN@2 | Readonly::
1 | 1 | 1 | 9µs | 25µs | BEGIN@3 | Readonly::
1 | 1 | 1 | 9µs | 23µs | BEGIN@155 | Readonly::
1 | 1 | 1 | 7µs | 25µs | BEGIN@19 | Readonly::
1 | 1 | 1 | 7µs | 39µs | BEGIN@42 | Readonly::
1 | 1 | 1 | 6µs | 44µs | BEGIN@156 | Readonly::
0 | 0 | 0 | 0s | 0s | Array | Readonly::
0 | 0 | 0 | 0s | 0s | Array1 | Readonly::
0 | 0 | 0 | 0s | 0s | FETCH | Readonly::Array::
0 | 0 | 0 | 0s | 0s | FETCHSIZE | Readonly::Array::
0 | 0 | 0 | 0s | 0s | TIEARRAY | Readonly::Array::
0 | 0 | 0 | 0s | 0s | __ANON__[:107] | Readonly::Array::
0 | 0 | 0 | 0s | 0s | Hash | Readonly::
0 | 0 | 0 | 0s | 0s | Hash1 | Readonly::
0 | 0 | 0 | 0s | 0s | EXISTS | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | FETCH | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | FIRSTKEY | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | NEXTKEY | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | TIEHASH | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | __ANON__[:148] | Readonly::Hash::
0 | 0 | 0 | 0s | 0s | Scalar | Readonly::
0 | 0 | 0 | 0s | 0s | Scalar1 | Readonly::
0 | 0 | 0 | 0s | 0s | FETCH | Readonly::Scalar::
0 | 0 | 0 | 0s | 0s | TIESCALAR | Readonly::Scalar::
0 | 0 | 0 | 0s | 0s | __ANON__[:69] | Readonly::Scalar::
0 | 0 | 0 | 0s | 0s | __ANON__[:25] | Readonly::
0 | 0 | 0 | 0s | 0s | __ANON__[:27] | Readonly::
0 | 0 | 0 | 0s | 0s | __ANON__[:35] | Readonly::
0 | 0 | 0 | 0s | 0s | __ANON__[:37] | Readonly::
0 | 0 | 0 | 0s | 0s | _is_badtype | Readonly::
0 | 0 | 0 | 0s | 0s | croak | Readonly::
Line | State ments |
Time on line |
Calls | Time in subs |
Code |
---|---|---|---|---|---|
1 | package Readonly; | ||||
2 | 2 | 70µs | 1 | 24µs | # spent 24µs within Readonly::BEGIN@2 which was called:
# once (24µs+0s) by Koha::Calendar::BEGIN@11 at line 2 # spent 24µs making 1 call to Readonly::BEGIN@2 |
3 | 2 | 70µs | 2 | 41µs | # spent 25µs (9+16) within Readonly::BEGIN@3 which was called:
# once (9µs+16µs) by Koha::Calendar::BEGIN@11 at line 3 # spent 25µs making 1 call to Readonly::BEGIN@3
# spent 16µs making 1 call to strict::import |
4 | |||||
5 | #use warnings; | ||||
6 | #no warnings 'uninitialized'; | ||||
7 | package Readonly; | ||||
8 | 1 | 600ns | our $VERSION = '2.00'; | ||
9 | 1 | 13µs | $VERSION = eval $VERSION; # spent 2µs executing statements in string eval | ||
10 | |||||
11 | # Autocroak (Thanks, MJD) | ||||
12 | # Only load Carp.pm if module is croaking. | ||||
13 | sub croak { | ||||
14 | require Carp; | ||||
15 | goto &Carp::croak; | ||||
16 | } | ||||
17 | |||||
18 | # These functions may be overridden by Readonly::XS, if installed. | ||||
19 | 2 | 134µs | 2 | 42µs | # spent 25µs (7+18) within Readonly::BEGIN@19 which was called:
# once (7µs+18µs) by Koha::Calendar::BEGIN@11 at line 19 # spent 25µs making 1 call to Readonly::BEGIN@19
# spent 18µs making 1 call to vars::import |
20 | |||||
21 | # For perl 5.8.x or higher | ||||
22 | # These functions are exposed in perl 5.8.x (Thanks, Leon!) | ||||
23 | # They may be overridden by Readonly::XS, if installed on old perl versions | ||||
24 | 1 | 900ns | if ($] < 5.008) { # 'Classic' perl | ||
25 | *is_sv_readonly = sub ($) {0}; | ||||
26 | *make_sv_readonly | ||||
27 | = sub ($) { die "make_sv_readonly called but not overridden" }; | ||||
28 | |||||
29 | # See if we can use the XS stuff. | ||||
30 | $Readonly::XS::MAGIC_COOKIE | ||||
31 | = "Do NOT use or require Readonly::XS unless you're me."; | ||||
32 | eval 'use Readonly::XS'; | ||||
33 | } | ||||
34 | else { # Modern perl doesn't need Readonly::XS | ||||
35 | 1 | 3µs | *is_sv_readonly = sub ($) { Internals::SvREADONLY($_[0]) }; | ||
36 | *make_sv_readonly | ||||
37 | 1 | 900ns | = sub ($) { Internals::SvREADONLY($_[0], 1) }; | ||
38 | 1 | 200ns | $XSokay = 1; # We're using the new built-ins so this is a white lie | ||
39 | } | ||||
40 | |||||
41 | # Common error messages, or portions thereof | ||||
42 | 2 | 296µs | 2 | 72µs | # spent 39µs (7+33) within Readonly::BEGIN@42 which was called:
# once (7µs+33µs) by Koha::Calendar::BEGIN@11 at line 42 # spent 39µs making 1 call to Readonly::BEGIN@42
# spent 32µs making 1 call to vars::import |
43 | 1 | 200ns | $MODIFY = 'Modification of a read-only value attempted'; | ||
44 | 1 | 100ns | $REASSIGN = 'Attempt to reassign a readonly'; | ||
45 | 1 | 100ns | $ODDHASH = 'May not store an odd number of values in a hash'; | ||
46 | |||||
47 | # ---------------- | ||||
48 | # Read-only scalars | ||||
49 | # ---------------- | ||||
50 | package Readonly::Scalar; | ||||
51 | |||||
52 | sub TIESCALAR { | ||||
53 | my $whence | ||||
54 | = (caller 2)[3]; # Check if naughty user is trying to tie directly. | ||||
55 | Readonly::croak "Invalid tie" | ||||
56 | unless $whence && $whence =~ /^Readonly::(?:Scalar1?|Readonly)$/; | ||||
57 | my $class = shift; | ||||
58 | Readonly::croak "No value specified for readonly scalar" unless @_; | ||||
59 | Readonly::croak "Too many values specified for readonly scalar" | ||||
60 | unless @_ == 1; | ||||
61 | my $value = shift; | ||||
62 | return bless \$value, $class; | ||||
63 | } | ||||
64 | |||||
65 | sub FETCH { | ||||
66 | my $self = shift; | ||||
67 | return $$self; | ||||
68 | } | ||||
69 | 1 | 2µs | *STORE = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
70 | |||||
71 | # ---------------- | ||||
72 | # Read-only arrays | ||||
73 | # ---------------- | ||||
74 | package Readonly::Array; | ||||
75 | |||||
76 | sub TIEARRAY { | ||||
77 | my $whence | ||||
78 | = (caller 1)[3]; # Check if naughty user is trying to tie directly. | ||||
79 | Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Array1?$/; | ||||
80 | my $class = shift; | ||||
81 | my @self = @_; | ||||
82 | return bless \@self, $class; | ||||
83 | } | ||||
84 | |||||
85 | sub FETCH { | ||||
86 | my $self = shift; | ||||
87 | my $index = shift; | ||||
88 | return $self->[$index]; | ||||
89 | } | ||||
90 | |||||
91 | sub FETCHSIZE { | ||||
92 | my $self = shift; | ||||
93 | return scalar @$self; | ||||
94 | } | ||||
95 | |||||
96 | # spent 38µs within Readonly::Array::BEGIN@96 which was called:
# once (38µs+0s) by Koha::Calendar::BEGIN@11 at line 105 | ||||
97 | 1 | 40µs | eval q{ | ||
98 | sub EXISTS | ||||
99 | { | ||||
100 | my $self = shift; | ||||
101 | my $index = shift; | ||||
102 | return exists $self->[$index]; | ||||
103 | } | ||||
104 | } if $] >= 5.006; # couldn't do "exists" on arrays before then | ||||
105 | 1 | 250µs | 1 | 38µs | } # spent 38µs making 1 call to Readonly::Array::BEGIN@96 |
106 | *STORE = *STORESIZE = *EXTEND = *PUSH = *POP = *UNSHIFT = *SHIFT = *SPLICE | ||||
107 | 1 | 2µs | = *CLEAR = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
108 | |||||
109 | # ---------------- | ||||
110 | # Read-only hashes | ||||
111 | # ---------------- | ||||
112 | package Readonly::Hash; | ||||
113 | |||||
114 | sub TIEHASH { | ||||
115 | my $whence | ||||
116 | = (caller 1)[3]; # Check if naughty user is trying to tie directly. | ||||
117 | Readonly::croak "Invalid tie" unless $whence =~ /^Readonly::Hash1?$/; | ||||
118 | my $class = shift; | ||||
119 | |||||
120 | # must have an even number of values | ||||
121 | Readonly::croak $Readonly::ODDHASH unless (@_ % 2 == 0); | ||||
122 | my %self = @_; | ||||
123 | return bless \%self, $class; | ||||
124 | } | ||||
125 | |||||
126 | sub FETCH { | ||||
127 | my $self = shift; | ||||
128 | my $key = shift; | ||||
129 | return $self->{$key}; | ||||
130 | } | ||||
131 | |||||
132 | sub EXISTS { | ||||
133 | my $self = shift; | ||||
134 | my $key = shift; | ||||
135 | return exists $self->{$key}; | ||||
136 | } | ||||
137 | |||||
138 | sub FIRSTKEY { | ||||
139 | my $self = shift; | ||||
140 | my $dummy = keys %$self; | ||||
141 | return scalar each %$self; | ||||
142 | } | ||||
143 | |||||
144 | sub NEXTKEY { | ||||
145 | my $self = shift; | ||||
146 | return scalar each %$self; | ||||
147 | } | ||||
148 | 1 | 1µs | *STORE = *DELETE = *CLEAR = *UNTIE = sub { Readonly::croak $Readonly::MODIFY}; | ||
149 | |||||
150 | # ---------------------------------------------------------------- | ||||
151 | # Main package, containing convenience functions (so callers won't | ||||
152 | # have to explicitly tie the variables themselves). | ||||
153 | # ---------------------------------------------------------------- | ||||
154 | package Readonly; | ||||
155 | 2 | 25µs | 2 | 38µs | # spent 23µs (9+15) within Readonly::BEGIN@155 which was called:
# once (9µs+15µs) by Koha::Calendar::BEGIN@11 at line 155 # spent 23µs making 1 call to Readonly::BEGIN@155
# spent 15µs making 1 call to Exporter::import |
156 | 2 | 1.05ms | 2 | 82µs | # spent 44µs (6+38) within Readonly::BEGIN@156 which was called:
# once (6µs+38µs) by Koha::Calendar::BEGIN@11 at line 156 # spent 44µs making 1 call to Readonly::BEGIN@156
# spent 38µs making 1 call to vars::import |
157 | 1 | 5µs | push @ISA, 'Exporter'; | ||
158 | 1 | 300ns | push @EXPORT, qw/Readonly/; | ||
159 | 1 | 700ns | push @EXPORT_OK, qw/Scalar Array Hash Scalar1 Array1 Hash1/; | ||
160 | |||||
161 | # Predeclare the following, so we can use them recursively | ||||
162 | sub Scalar ($$); | ||||
163 | sub Array (\@;@); | ||||
164 | sub Hash (\%;@); | ||||
165 | |||||
166 | # Returns true if a string begins with "Readonly::" | ||||
167 | # Used to prevent reassignment of Readonly variables. | ||||
168 | sub _is_badtype { | ||||
169 | my $type = $_[0]; | ||||
170 | return lc $type if $type =~ s/^Readonly:://; | ||||
171 | return; | ||||
172 | } | ||||
173 | |||||
174 | # Shallow Readonly scalar | ||||
175 | sub Scalar1 ($$) { | ||||
176 | croak "$REASSIGN scalar" if is_sv_readonly($_[0]); | ||||
177 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
178 | croak "$REASSIGN $badtype" if $badtype; | ||||
179 | |||||
180 | # xs method: flag scalar as readonly | ||||
181 | if ($XSokay) { | ||||
182 | $_[0] = $_[1]; | ||||
183 | make_sv_readonly($_[0]); | ||||
184 | return; | ||||
185 | } | ||||
186 | |||||
187 | # pure-perl method: tied scalar | ||||
188 | my $tieobj = eval { tie $_[0], 'Readonly::Scalar', $_[1] }; | ||||
189 | if ($@) { | ||||
190 | croak "$REASSIGN scalar" if substr($@, 0, 43) eq $MODIFY; | ||||
191 | die $@; # some other error? | ||||
192 | } | ||||
193 | return $tieobj; | ||||
194 | } | ||||
195 | |||||
196 | # Shallow Readonly array | ||||
197 | sub Array1 (\@;@) { | ||||
198 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
199 | croak "$REASSIGN $badtype" if $badtype; | ||||
200 | my $aref = shift; | ||||
201 | return tie @$aref, 'Readonly::Array', @_; | ||||
202 | } | ||||
203 | |||||
204 | # Shallow Readonly hash | ||||
205 | sub Hash1 (\%;@) { | ||||
206 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
207 | croak "$REASSIGN $badtype" if $badtype; | ||||
208 | my $href = shift; | ||||
209 | |||||
210 | # If only one value, and it's a hashref, expand it | ||||
211 | if (@_ == 1 && ref $_[0] eq 'HASH') { | ||||
212 | return tie %$href, 'Readonly::Hash', %{$_[0]}; | ||||
213 | } | ||||
214 | |||||
215 | # otherwise, must have an even number of values | ||||
216 | croak $ODDHASH unless (@_ % 2 == 0); | ||||
217 | return tie %$href, 'Readonly::Hash', @_; | ||||
218 | } | ||||
219 | |||||
220 | # Deep Readonly scalar | ||||
221 | sub Scalar ($$) { | ||||
222 | croak "$REASSIGN scalar" if is_sv_readonly($_[0]); | ||||
223 | my $badtype = _is_badtype(ref tied $_[0]); | ||||
224 | croak "$REASSIGN $badtype" if $badtype; | ||||
225 | my $value = $_[1]; | ||||
226 | |||||
227 | # Recursively check passed element for references; if any, make them Readonly | ||||
228 | foreach ($value) { | ||||
229 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
230 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
231 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
232 | } | ||||
233 | |||||
234 | # xs method: flag scalar as readonly | ||||
235 | if ($XSokay) { | ||||
236 | $_[0] = $value; | ||||
237 | make_sv_readonly($_[0]); | ||||
238 | return; | ||||
239 | } | ||||
240 | |||||
241 | # pure-perl method: tied scalar | ||||
242 | my $tieobj = eval { tie $_[0], 'Readonly::Scalar', $value }; | ||||
243 | if ($@) { | ||||
244 | croak "$REASSIGN scalar" if substr($@, 0, 43) eq $MODIFY; | ||||
245 | die $@; # some other error? | ||||
246 | } | ||||
247 | return $tieobj; | ||||
248 | } | ||||
249 | |||||
250 | # Deep Readonly array | ||||
251 | sub Array (\@;@) { | ||||
252 | my $badtype = _is_badtype(ref tied @{$_[0]}); | ||||
253 | croak "$REASSIGN $badtype" if $badtype; | ||||
254 | my $aref = shift; | ||||
255 | my @values = @_; | ||||
256 | |||||
257 | # Recursively check passed elements for references; if any, make them Readonly | ||||
258 | foreach (@values) { | ||||
259 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
260 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
261 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
262 | } | ||||
263 | |||||
264 | # Lastly, tie the passed reference | ||||
265 | return tie @$aref, 'Readonly::Array', @values; | ||||
266 | } | ||||
267 | |||||
268 | # Deep Readonly hash | ||||
269 | sub Hash (\%;@) { | ||||
270 | my $badtype = _is_badtype(ref tied %{$_[0]}); | ||||
271 | croak "$REASSIGN $badtype" if $badtype; | ||||
272 | my $href = shift; | ||||
273 | my @values = @_; | ||||
274 | |||||
275 | # If only one value, and it's a hashref, expand it | ||||
276 | if (@_ == 1 && ref $_[0] eq 'HASH') { | ||||
277 | @values = %{$_[0]}; | ||||
278 | } | ||||
279 | |||||
280 | # otherwise, must have an even number of values | ||||
281 | croak $ODDHASH unless (@values % 2 == 0); | ||||
282 | |||||
283 | # Recursively check passed elements for references; if any, make them Readonly | ||||
284 | foreach (@values) { | ||||
285 | if (ref eq 'SCALAR') { Scalar my $v => $$_; $_ = \$v } | ||||
286 | elsif (ref eq 'ARRAY') { Array my @v => @$_; $_ = \@v } | ||||
287 | elsif (ref eq 'HASH') { Hash my %v => $_; $_ = \%v } | ||||
288 | } | ||||
289 | return tie %$href, 'Readonly::Hash', @values; | ||||
290 | } | ||||
291 | |||||
292 | # Common entry-point for all supported data types | ||||
293 | 1 | 182µs | eval q{sub Readonly} . ($] < 5.008 ? '' : '(\[$@%]@)') . <<'SUB_READONLY'; | ||
294 | { | ||||
295 | if (ref $_[0] eq 'SCALAR') | ||||
296 | { | ||||
297 | croak $MODIFY if is_sv_readonly ${$_[0]}; | ||||
298 | my $badtype = _is_badtype (ref tied ${$_[0]}); | ||||
299 | croak "$REASSIGN $badtype" if $badtype; | ||||
300 | croak "Readonly scalar must have only one value" if @_ > 2; | ||||
301 | |||||
302 | my $tieobj = eval {tie ${$_[0]}, 'Readonly::Scalar', $_[1]}; | ||||
303 | # Tie may have failed because user tried to tie a constant, or we screwed up somehow. | ||||
304 | if ($@) | ||||
305 | { | ||||
306 | croak $MODIFY if $@ =~ /^$MODIFY at/; # Point the finger at the user. | ||||
307 | die "$@\n"; # Not a modify read-only message; must be our fault. | ||||
308 | } | ||||
309 | return $tieobj; | ||||
310 | } | ||||
311 | elsif (ref $_[0] eq 'ARRAY') | ||||
312 | { | ||||
313 | my $aref = shift; | ||||
314 | return Array @$aref, @_; | ||||
315 | } | ||||
316 | elsif (ref $_[0] eq 'HASH') | ||||
317 | { | ||||
318 | my $href = shift; | ||||
319 | croak $ODDHASH if @_%2 != 0 && !(@_ == 1 && ref $_[0] eq 'HASH'); | ||||
320 | return Hash %$href, @_; | ||||
321 | } | ||||
322 | elsif (ref $_[0]) | ||||
323 | { | ||||
324 | croak "Readonly only supports scalar, array, and hash variables."; | ||||
325 | } | ||||
326 | else | ||||
327 | { | ||||
328 | croak "First argument to Readonly must be a reference."; | ||||
329 | } | ||||
330 | } | ||||
331 | SUB_READONLY | ||||
332 | 1 | 7µs | 1; | ||
333 | |||||
334 | =head1 NAME | ||||
335 | |||||
336 | Readonly - Facility for creating read-only scalars, arrays, hashes | ||||
337 | |||||
338 | =head1 Synopsis | ||||
339 | |||||
340 | use Readonly; | ||||
341 | |||||
342 | # Deep Read-only scalar | ||||
343 | Readonly::Scalar $sca => $initial_value; | ||||
344 | Readonly::Scalar my $sca => $initial_value; | ||||
345 | |||||
346 | # Deep Read-only array | ||||
347 | Readonly::Array @arr => @values; | ||||
348 | Readonly::Array my @arr => @values; | ||||
349 | |||||
350 | # Deep Read-only hash | ||||
351 | Readonly::Hash %has => (key => value, key => value, ...); | ||||
352 | Readonly::Hash my %has => (key => value, key => value, ...); | ||||
353 | # or: | ||||
354 | Readonly::Hash %has => {key => value, key => value, ...}; | ||||
355 | |||||
356 | # You can use the read-only variables like any regular variables: | ||||
357 | print $sca; | ||||
358 | $something = $sca + $arr[2]; | ||||
359 | next if $has{$some_key}; | ||||
360 | |||||
361 | # But if you try to modify a value, your program will die: | ||||
362 | $sca = 7; | ||||
363 | push @arr, 'seven'; | ||||
364 | delete $has{key}; | ||||
365 | # The error message is "Modification of a read-only value attempted" | ||||
366 | |||||
367 | # Alternate form (Perl 5.8 and later) | ||||
368 | Readonly $sca => $initial_value; | ||||
369 | Readonly my $sca => $initial_value; | ||||
370 | Readonly @arr => @values; | ||||
371 | Readonly my @arr => @values; | ||||
372 | Readonly %has => (key => value, key => value, ...); | ||||
373 | Readonly my %has => (key => value, key => value, ...); | ||||
374 | Readonly my $sca; # Implicit undef, readonly value | ||||
375 | |||||
376 | # Alternate form (for Perls earlier than v5.8) | ||||
377 | Readonly \$sca => $initial_value; | ||||
378 | Readonly \my $sca => $initial_value; | ||||
379 | Readonly \@arr => @values; | ||||
380 | Readonly \my @arr => @values; | ||||
381 | Readonly \%has => (key => value, key => value, ...); | ||||
382 | Readonly \my %has => (key => value, key => value, ...); | ||||
383 | |||||
384 | =head1 Description | ||||
385 | |||||
386 | This is a facility for creating non-modifiable variables. This is useful for | ||||
387 | configuration files, headers, etc. It can also be useful as a development and | ||||
388 | debugging tool for catching updates to variables that should not be changed. | ||||
389 | |||||
390 | =head1 Variable Depth | ||||
391 | |||||
392 | Readonly has the ability to create both deep and shallow readonly variables. | ||||
393 | |||||
394 | If any of the values you pass to C<Scalar>, C<Array>, C<Hash>, or the standard | ||||
395 | C<Readonly> are references, then those functions recurse over the data | ||||
396 | structures, marking everything as Readonly. The entire structure is | ||||
397 | nonmodifiable. This is normally what you want. | ||||
398 | |||||
399 | If you want only the top level to be Readonly, use the alternate (and poorly | ||||
400 | named) C<Scalar1>, C<Array1>, and C<Hash1> functions. | ||||
401 | |||||
402 | =head1 | ||||
403 | |||||
404 | =head1 The Past | ||||
405 | |||||
406 | The following sections are updated versions of the previous authors | ||||
407 | documentation. | ||||
408 | |||||
409 | =head2 Comparison with "use constant" | ||||
410 | |||||
411 | Perl provides a facility for creating constant values, via the L<constant> | ||||
412 | pragma. There are several problems with this pragma. | ||||
413 | |||||
414 | =over 2 | ||||
415 | |||||
416 | =item * The constants created have no leading sigils. | ||||
417 | |||||
418 | =item * These constants cannot be interpolated into strings. | ||||
419 | |||||
420 | =item * Syntax can get dicey sometimes. For example: | ||||
421 | |||||
422 | use constant CARRAY => (2, 3, 5, 7, 11, 13); | ||||
423 | $a_prime = CARRAY[2]; # wrong! | ||||
424 | $a_prime = (CARRAY)[2]; # right -- MUST use parentheses | ||||
425 | |||||
426 | =item * You have to be very careful in places where barewords are allowed. | ||||
427 | |||||
428 | For example: | ||||
429 | |||||
430 | use constant SOME_KEY => 'key'; | ||||
431 | %hash = (key => 'value', other_key => 'other_value'); | ||||
432 | $some_value = $hash{SOME_KEY}; # wrong! | ||||
433 | $some_value = $hash{+SOME_KEY}; # right | ||||
434 | |||||
435 | (who thinks to use a unary plus when using a hash to scalarize the key?) | ||||
436 | |||||
437 | =item * C<use constant> works for scalars and arrays, not hashes. | ||||
438 | |||||
439 | =item * These constants are global to the package in which they're declared; | ||||
440 | cannot be lexically scoped. | ||||
441 | |||||
442 | =item * Works only at compile time. | ||||
443 | |||||
444 | =item * Can be overridden: | ||||
445 | |||||
446 | use constant PI => 3.14159; | ||||
447 | ... | ||||
448 | use constant PI => 2.71828; | ||||
449 | |||||
450 | (this does generate a warning, however, if you have warnings enabled). | ||||
451 | |||||
452 | =item * It is very difficult to make and use deep structures (complex data | ||||
453 | structures) with C<use constant>. | ||||
454 | |||||
455 | =back | ||||
456 | |||||
457 | =head1 Comparison with typeglob constants | ||||
458 | |||||
459 | Another popular way to create read-only scalars is to modify the symbol table | ||||
460 | entry for the variable by using a typeglob: | ||||
461 | |||||
462 | *a = \'value'; | ||||
463 | |||||
464 | This works fine, but it only works for global variables ("my" variables have | ||||
465 | no symbol table entry). Also, the following similar constructs do B<not> work: | ||||
466 | |||||
467 | *a = [1, 2, 3]; # Does NOT create a read-only array | ||||
468 | *a = { a => 'A'}; # Does NOT create a read-only hash | ||||
469 | |||||
470 | =head2 Pros | ||||
471 | |||||
472 | Readonly.pm, on the other hand, will work with global variables and with | ||||
473 | lexical ("my") variables. It will create scalars, arrays, or hashes, all of | ||||
474 | which look and work like normal, read-write Perl variables. You can use them | ||||
475 | in scalar context, in list context; you can take references to them, pass them | ||||
476 | to functions, anything. | ||||
477 | |||||
478 | Readonly.pm also works well with complex data structures, allowing you to tag | ||||
479 | the whole structure as nonmodifiable, or just the top level. | ||||
480 | |||||
481 | Also, Readonly variables may not be reassigned. The following code will die: | ||||
482 | |||||
483 | Readonly::Scalar $pi => 3.14159; | ||||
484 | ... | ||||
485 | Readonly::Scalar $pi => 2.71828; | ||||
486 | |||||
487 | =head2 Cons | ||||
488 | |||||
489 | Readonly.pm used to impose a performance penalty. It was pretty slow. How | ||||
490 | slow? Run the C<eg/benchmark.pl> script that comes with Readonly. On my test | ||||
491 | system, "use constant" (const), typeglob constants (tglob), regular read/write | ||||
492 | Perl variables (normal/literal), and the new Readonly (ro/ro_simple) are all | ||||
493 | about the same speed, the old, tie based Readonly.pm constants were about 1/22 | ||||
494 | the speed. | ||||
495 | |||||
496 | However, there is relief. There is a companion module available, Readonly::XS. | ||||
497 | You won't need this if you're using Perl 5.8.x or higher. | ||||
498 | |||||
499 | I repeat, you do not need Readonly::XS if your environment has perl 5.8.x or | ||||
500 | higher. Please see section entitled L<Internals|/"Internals"> for more. | ||||
501 | |||||
502 | =head1 Functions | ||||
503 | |||||
504 | =over 4 | ||||
505 | |||||
506 | =item Readonly::Scalar $var => $value; | ||||
507 | |||||
508 | Creates a nonmodifiable scalar, C<$var>, and assigns a value of C<$value> to | ||||
509 | it. Thereafter, its value may not be changed. Any attempt to modify the value | ||||
510 | will cause your program to die. | ||||
511 | |||||
512 | A value I<must> be supplied. If you want the variable to have C<undef> as its | ||||
513 | value, you must specify C<undef>. | ||||
514 | |||||
515 | If C<$value> is a reference to a scalar, array, or hash, then this function | ||||
516 | will mark the scalar, array, or hash it points to as being Readonly as well, | ||||
517 | and it will recursively traverse the structure, marking the whole thing as | ||||
518 | Readonly. Usually, this is what you want. However, if you want only the | ||||
519 | C<$value> marked as Readonly, use C<Scalar1>. | ||||
520 | |||||
521 | If $var is already a Readonly variable, the program will die with an error | ||||
522 | about reassigning Readonly variables. | ||||
523 | |||||
524 | =item Readonly::Array @arr => (value, value, ...); | ||||
525 | |||||
526 | Creates a nonmodifiable array, C<@arr>, and assigns the specified list of | ||||
527 | values to it. Thereafter, none of its values may be changed; the array may not | ||||
528 | be lengthened or shortened or spliced. Any attempt to do so will cause your | ||||
529 | program to die. | ||||
530 | |||||
531 | If any of the values passed is a reference to a scalar, array, or hash, then | ||||
532 | this function will mark the scalar, array, or hash it points to as being | ||||
533 | Readonly as well, and it will recursively traverse the structure, marking the | ||||
534 | whole thing as Readonly. Usually, this is what you want. However, if you want | ||||
535 | only the hash C<%@arr> itself marked as Readonly, use C<Array1>. | ||||
536 | |||||
537 | If C<@arr> is already a Readonly variable, the program will die with an error | ||||
538 | about reassigning Readonly variables. | ||||
539 | |||||
540 | =item Readonly::Hash %h => (key => value, key => value, ...); | ||||
541 | |||||
542 | =item Readonly::Hash %h => {key => value, key => value, ...}; | ||||
543 | |||||
544 | Creates a nonmodifiable hash, C<%h>, and assigns the specified keys and values | ||||
545 | to it. Thereafter, its keys or values may not be changed. Any attempt to do so | ||||
546 | will cause your program to die. | ||||
547 | |||||
548 | A list of keys and values may be specified (with parentheses in the synopsis | ||||
549 | above), or a hash reference may be specified (curly braces in the synopsis | ||||
550 | above). If a list is specified, it must have an even number of elements, or | ||||
551 | the function will die. | ||||
552 | |||||
553 | If any of the values is a reference to a scalar, array, or hash, then this | ||||
554 | function will mark the scalar, array, or hash it points to as being Readonly | ||||
555 | as well, and it will recursively traverse the structure, marking the whole | ||||
556 | thing as Readonly. Usually, this is what you want. However, if you want only | ||||
557 | the hash C<%h> itself marked as Readonly, use C<Hash1>. | ||||
558 | |||||
559 | If C<%h> is already a Readonly variable, the program will die with an error | ||||
560 | about reassigning Readonly variables. | ||||
561 | |||||
562 | =item Readonly $var => $value; | ||||
563 | |||||
564 | =item Readonly @arr => (value, value, ...); | ||||
565 | |||||
566 | =item Readonly %h => (key => value, ...); | ||||
567 | |||||
568 | =item Readonly %h => {key => value, ...}; | ||||
569 | |||||
570 | =item Readonly $var; | ||||
571 | |||||
572 | The C<Readonly> function is an alternate to the C<Scalar>, C<Array>, and | ||||
573 | C<Hash> functions. It has the advantage (if you consider it an advantage) of | ||||
574 | being one function. That may make your program look neater, if you're | ||||
575 | initializing a whole bunch of constants at once. You may or may not prefer | ||||
576 | this uniform style. | ||||
577 | |||||
578 | It has the disadvantage of having a slightly different syntax for versions of | ||||
579 | Perl prior to 5.8. For earlier versions, you must supply a backslash, because | ||||
580 | it requires a reference as the first parameter. | ||||
581 | |||||
582 | Readonly \$var => $value; | ||||
583 | Readonly \@arr => (value, value, ...); | ||||
584 | Readonly \%h => (key => value, ...); | ||||
585 | Readonly \%h => {key => value, ...}; | ||||
586 | |||||
587 | You may or may not consider this ugly. | ||||
588 | |||||
589 | Note that you can create implicit undefined variables with this function like | ||||
590 | so C<Readonly my $var;> while a verbose undefined value must be passed to the | ||||
591 | standard C<Scalar>, C<Array>, and C<Hash> functions. | ||||
592 | |||||
593 | =item Readonly::Scalar1 $var => $value; | ||||
594 | |||||
595 | =item Readonly::Array1 @arr => (value, value, ...); | ||||
596 | |||||
597 | =item Readonly::Hash1 %h => (key => value, key => value, ...); | ||||
598 | |||||
599 | =item Readonly::Hash1 %h => {key => value, key => value, ...}; | ||||
600 | |||||
601 | These alternate functions create shallow Readonly variables, instead of deep | ||||
602 | ones. For example: | ||||
603 | |||||
604 | Readonly::Array1 @shal => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5); | ||||
605 | Readonly::Array @deep => (1, 2, {perl=>'Rules', java=>'Bites'}, 4, 5); | ||||
606 | |||||
607 | $shal[1] = 7; # error | ||||
608 | $shal[2]{APL}='Weird'; # Allowed! since the hash isn't Readonly | ||||
609 | $deep[1] = 7; # error | ||||
610 | $deep[2]{APL}='Weird'; # error, since the hash is Readonly | ||||
611 | |||||
612 | =back | ||||
613 | |||||
614 | =head1 Examples | ||||
615 | |||||
616 | These are a few very simple examples: | ||||
617 | |||||
618 | =head2 Scalars | ||||
619 | |||||
620 | A plain old read-only value | ||||
621 | |||||
622 | Readonly::Scalar $a => "A string value"; | ||||
623 | |||||
624 | The value need not be a compile-time constant: | ||||
625 | |||||
626 | Readonly::Scalar $a => $computed_value; | ||||
627 | |||||
628 | =head2 Arrays/Lists | ||||
629 | |||||
630 | A read-only array: | ||||
631 | |||||
632 | Readonly::Array @a => (1, 2, 3, 4); | ||||
633 | |||||
634 | The parentheses are optional: | ||||
635 | |||||
636 | Readonly::Array @a => 1, 2, 3, 4; | ||||
637 | |||||
638 | You can use Perl's built-in array quoting syntax: | ||||
639 | |||||
640 | Readonly::Array @a => qw/1 2 3 4/; | ||||
641 | |||||
642 | You can initialize a read-only array from a variable one: | ||||
643 | |||||
644 | Readonly::Array @a => @computed_values; | ||||
645 | |||||
646 | A read-only array can be empty, too: | ||||
647 | |||||
648 | Readonly::Array @a => (); | ||||
649 | Readonly::Array @a; # equivalent | ||||
650 | |||||
651 | =head2 Hashes | ||||
652 | |||||
653 | Typical usage: | ||||
654 | |||||
655 | Readonly::Hash %a => (key1 => 'value1', key2 => 'value2'); | ||||
656 | |||||
657 | A read-only hash can be initialized from a variable one: | ||||
658 | |||||
659 | Readonly::Hash %a => %computed_values; | ||||
660 | |||||
661 | A read-only hash can be empty: | ||||
662 | |||||
663 | Readonly::Hash %a => (); | ||||
664 | Readonly::Hash %a; # equivalent | ||||
665 | |||||
666 | If you pass an odd number of values, the program will die: | ||||
667 | |||||
668 | Readonly::Hash %a => (key1 => 'value1', "value2"); | ||||
669 | # This dies with "May not store an odd number of values in a hash" | ||||
670 | |||||
671 | =head1 Exports | ||||
672 | |||||
673 | Historically, this module exports the C<Readonly> symbol into the calling | ||||
674 | program's namespace by default. The following symbols are also available for | ||||
675 | import into your program, if you like: C<Scalar>, C<Scalar1>, C<Array>, | ||||
676 | C<Array1>, C<Hash>, and C<Hash1>. | ||||
677 | |||||
678 | =head1 Internals | ||||
679 | |||||
680 | Some people simply do not understand the relationship between this module and | ||||
681 | Readonly::XS so I'm adding this section. Odds are, they still won't understand | ||||
682 | but I like to write so... | ||||
683 | |||||
684 | In the past, Readonly's "magic" was performed by C<tie()>-ing variables to the | ||||
685 | C<Readonly::Scalar>, C<Readonly::Array>, and C<Readonly::Hash> packages (not | ||||
686 | to be confused with the functions of the same names) and acting on C<WRITE>, | ||||
687 | C<READ>, et. al. While this worked well, it was slow. Very slow. Like 20-30 | ||||
688 | times slower than accessing variables directly or using one of the other | ||||
689 | const-related modules that have cropped up since Readonly was released in | ||||
690 | 2003. | ||||
691 | |||||
692 | To 'fix' this, Readonly::XS was written. If installed, Readonly::XS used the | ||||
693 | internal methods C<SvREADONLY> and C<SvREADONLY_on> to lock simple scalars. On | ||||
694 | the surface, everything was peachy but things weren't the same behind the | ||||
695 | scenes. In edge cases, code perfromed very differently if Readonly::XS was | ||||
696 | installed and because it wasn't a required dependency in most code, it made | ||||
697 | downstream bugs very hard to track. | ||||
698 | |||||
699 | In the years since Readonly::XS was released, the then private internal | ||||
700 | methods have been exposed and can be used in pure perl. Similar modules were | ||||
701 | written to take advantage of this and a patch to Readonly was created. We no | ||||
702 | longer need to build and install another module to make Readonly useful on | ||||
703 | modern builds of perl. | ||||
704 | |||||
705 | =over | ||||
706 | |||||
707 | =item * You do not need to install Readonly::XS. | ||||
708 | |||||
709 | =item * You should stop listing Readonly::XS as a dependency or expect it to | ||||
710 | be installed. | ||||
711 | |||||
712 | =item * Stop testing the C<$Readonly::XSokay> variable! | ||||
713 | |||||
714 | =back | ||||
715 | |||||
716 | =head1 Requirements | ||||
717 | |||||
718 | Please note that most users of Readonly no longer need to install the | ||||
719 | companion module Readonly::XS which is recommended but not required for perl | ||||
720 | 5.6.x and under. Please do not force it as a requirement in new code and do | ||||
721 | not use the package variable C<$Readonly::XSokay> in code/tests. For more, see | ||||
722 | L<the section on Readonly's new internals/Internals>. | ||||
723 | |||||
724 | There are no non-core requirements. | ||||
725 | |||||
726 | =head1 Bug Reports | ||||
727 | |||||
728 | If email is better for you, L<my address is mentioned below|/"Author"> but I | ||||
729 | would rather have bugs sent through the issue tracker found at | ||||
730 | http://github.com/sanko/readonly/issues. | ||||
731 | |||||
732 | Please check the TODO file included with this distribution in case your bug | ||||
733 | is already known (...I probably won't file bug reports to myself). | ||||
734 | |||||
735 | =head1 Acknowledgements | ||||
736 | |||||
737 | Thanks to Slaven Rezic for the idea of one common function (Readonly) for all | ||||
738 | three types of variables (13 April 2002). | ||||
739 | |||||
740 | Thanks to Ernest Lergon for the idea (and initial code) for deeply-Readonly | ||||
741 | data structures (21 May 2002). | ||||
742 | |||||
743 | Thanks to Damian Conway for the idea (and code) for making the Readonly | ||||
744 | function work a lot smoother under perl 5.8+. | ||||
745 | |||||
746 | =head1 Author | ||||
747 | |||||
748 | Sanko Robinson <sanko@cpan.org> - http://sankorobinson.com/ | ||||
749 | |||||
750 | CPAN ID: SANKO | ||||
751 | |||||
752 | Original author: Eric J. Roode, roode@cpan.org | ||||
753 | |||||
754 | =head1 License and Legal | ||||
755 | |||||
756 | Copyright (C) 2013, 2014 by Sanko Robinson <sanko@cpan.org> | ||||
757 | |||||
758 | Copyright (c) 2001-2004 by Eric J. Roode. All Rights Reserved. | ||||
759 | |||||
760 | This module is free software; you can redistribute it and/or modify it under | ||||
761 | the same terms as Perl itself. | ||||
762 | |||||
763 | =cut |