Commit | Line | Data |
0e9b9e0c |
1 | ============================================================================== |
b9243681 |
2 | Attribute::Handlers |
0e9b9e0c |
3 | ============================================================================== |
4 | |
5 | |
6 | NAME |
7 | Attribute::Handlers - Simpler definition of attribute handlers |
8 | |
b9243681 |
9 | VERSION |
10 | This document describes version 0.79 of Attribute::Handlers, released |
11 | November 25, 2007. |
12 | |
13 | SYNOPSIS |
14 | package MyClass; |
12c541f4 |
15 | require 5.006; |
b9243681 |
16 | use Attribute::Handlers; |
17 | no warnings 'redefine'; |
18 | |
19 | |
20 | sub Good : ATTR(SCALAR) { |
21 | my ($package, $symbol, $referent, $attr, $data) = @_; |
22 | |
23 | # Invoked for any scalar variable with a :Good attribute, |
24 | # provided the variable was declared in MyClass (or |
25 | # a derived class) or typed to MyClass. |
26 | |
27 | # Do whatever to $referent here (executed in CHECK phase). |
28 | ... |
29 | } |
30 | |
31 | sub Bad : ATTR(SCALAR) { |
32 | # Invoked for any scalar variable with a :Bad attribute, |
33 | # provided the variable was declared in MyClass (or |
34 | # a derived class) or typed to MyClass. |
35 | ... |
36 | } |
37 | |
38 | sub Good : ATTR(ARRAY) { |
39 | # Invoked for any array variable with a :Good attribute, |
40 | # provided the variable was declared in MyClass (or |
41 | # a derived class) or typed to MyClass. |
42 | ... |
43 | } |
44 | |
45 | sub Good : ATTR(HASH) { |
46 | # Invoked for any hash variable with a :Good attribute, |
47 | # provided the variable was declared in MyClass (or |
48 | # a derived class) or typed to MyClass. |
49 | ... |
50 | } |
51 | |
52 | sub Ugly : ATTR(CODE) { |
53 | # Invoked for any subroutine declared in MyClass (or a |
54 | # derived class) with an :Ugly attribute. |
55 | ... |
56 | } |
57 | |
58 | sub Omni : ATTR { |
59 | # Invoked for any scalar, array, hash, or subroutine |
60 | # with an :Omni attribute, provided the variable or |
61 | # subroutine was declared in MyClass (or a derived class) |
62 | # or the variable was typed to MyClass. |
63 | # Use ref($_[2]) to determine what kind of referent it was. |
64 | ... |
65 | } |
66 | |
67 | |
68 | use Attribute::Handlers autotie => { Cycle => Tie::Cycle }; |
69 | |
70 | my $next : Cycle(['A'..'Z']); |
71 | |
0e9b9e0c |
72 | DESCRIPTION |
73 | This module, when inherited by a package, allows that package's class to |
74 | define attribute handler subroutines for specific attributes. Variables |
75 | and subroutines subsequently defined in that package, or in packages |
76 | derived from that package may be given attributes with the same names as |
b9243681 |
77 | the attribute handler subroutines, which will then be called in one of |
78 | the compilation phases (i.e. in a "BEGIN", "CHECK", "INIT", or "END" |
79 | block). ("UNITCHECK" blocks don't correspond to a global compilation |
80 | phase, so they can't be specified here.) |
0e9b9e0c |
81 | |
b9243681 |
82 | To create a handler, define it as a subroutine with the same name as the |
83 | desired attribute, and declare the subroutine itself with the attribute |
84 | ":ATTR". For example: |
0e9b9e0c |
85 | |
b9243681 |
86 | package LoudDecl; |
87 | use Attribute::Handlers; |
0e9b9e0c |
88 | |
b9243681 |
89 | sub Loud :ATTR { |
90 | my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_; |
91 | print STDERR |
92 | ref($referent), " ", |
93 | *{$symbol}{NAME}, " ", |
94 | "($referent) ", "was just declared ", |
95 | "and ascribed the ${attr} attribute ", |
96 | "with data ($data)\n", |
97 | "in phase $phase\n", |
98 | "in file $filename at line $linenum\n"; |
99 | } |
0e9b9e0c |
100 | |
b9243681 |
101 | This creates a handler for the attribute ":Loud" in the class LoudDecl. |
102 | Thereafter, any subroutine declared with a ":Loud" attribute in the |
103 | class LoudDecl: |
0e9b9e0c |
104 | |
b9243681 |
105 | package LoudDecl; |
0e9b9e0c |
106 | |
b9243681 |
107 | sub foo: Loud {...} |
0e9b9e0c |
108 | |
b9243681 |
109 | causes the above handler to be invoked, and passed: |
0e9b9e0c |
110 | |
b9243681 |
111 | [0] the name of the package into which it was declared; |
0e9b9e0c |
112 | |
b9243681 |
113 | [1] a reference to the symbol table entry (typeglob) containing the |
114 | subroutine; |
0e9b9e0c |
115 | |
b9243681 |
116 | [2] a reference to the subroutine; |
0e9b9e0c |
117 | |
b9243681 |
118 | [3] the name of the attribute; |
0e9b9e0c |
119 | |
b9243681 |
120 | [4] any data associated with that attribute; |
0e9b9e0c |
121 | |
b9243681 |
122 | [5] the name of the phase in which the handler is being invoked; |
0e9b9e0c |
123 | |
b9243681 |
124 | [6] the filename in which the handler is being invoked; |
0e9b9e0c |
125 | |
b9243681 |
126 | [7] the line number in this file. |
0e9b9e0c |
127 | |
b9243681 |
128 | Likewise, declaring any variables with the ":Loud" attribute within the |
129 | package: |
0e9b9e0c |
130 | |
b9243681 |
131 | package LoudDecl; |
0e9b9e0c |
132 | |
b9243681 |
133 | my $foo :Loud; |
134 | my @foo :Loud; |
135 | my %foo :Loud; |
0e9b9e0c |
136 | |
b9243681 |
137 | will cause the handler to be called with a similar argument list |
138 | (except, of course, that $_[2] will be a reference to the variable). |
0e9b9e0c |
139 | |
b9243681 |
140 | The package name argument will typically be the name of the class into |
141 | which the subroutine was declared, but it may also be the name of a |
142 | derived class (since handlers are inherited). |
143 | |
144 | If a lexical variable is given an attribute, there is no symbol table to |
145 | which it belongs, so the symbol table argument ($_[1]) is set to the |
146 | string 'LEXICAL' in that case. Likewise, ascribing an attribute to an |
147 | anonymous subroutine results in a symbol table argument of 'ANON'. |
148 | |
149 | The data argument passes in the value (if any) associated with the |
150 | attribute. For example, if &foo had been declared: |
151 | |
152 | sub foo :Loud("turn it up to 11, man!") {...} |
153 | |
154 | then a reference to an array containing the string "turn it up to 11, |
155 | man!" would be passed as the last argument. |
156 | |
157 | Attribute::Handlers makes strenuous efforts to convert the data argument |
158 | ($_[4]) to a useable form before passing it to the handler (but see |
159 | "Non-interpretive attribute handlers"). If those efforts succeed, the |
160 | interpreted data is passed in an array reference; if they fail, the raw |
161 | data is passed as a string. For example, all of these: |
162 | |
163 | sub foo :Loud(till=>ears=>are=>bleeding) {...} |
164 | sub foo :Loud(qw/till ears are bleeding/) {...} |
165 | sub foo :Loud(qw/my, ears, are, bleeding/) {...} |
166 | sub foo :Loud(till,ears,are,bleeding) {...} |
167 | |
168 | causes it to pass "['till','ears','are','bleeding']" as the handler's |
169 | data argument. While: |
170 | |
171 | sub foo :Loud(['till','ears','are','bleeding']) {...} |
172 | |
173 | causes it to pass "[ ['till','ears','are','bleeding'] ]"; the array |
174 | reference specified in the data being passed inside the standard array |
175 | reference indicating successful interpretation. |
176 | |
177 | However, if the data can't be parsed as valid Perl, then it is passed as |
178 | an uninterpreted string. For example: |
179 | |
180 | sub foo :Loud(my,ears,are,bleeding) {...} |
181 | sub foo :Loud(qw/my ears are bleeding) {...} |
182 | |
183 | cause the strings 'my,ears,are,bleeding' and 'qw/my ears are bleeding' |
184 | respectively to be passed as the data argument. |
185 | |
186 | If no value is associated with the attribute, "undef" is passed. |
187 | |
188 | Typed lexicals |
189 | Regardless of the package in which it is declared, if a lexical variable |
190 | is ascribed an attribute, the handler that is invoked is the one |
191 | belonging to the package to which it is typed. For example, the |
192 | following declarations: |
193 | |
194 | package OtherClass; |
195 | |
196 | my LoudDecl $loudobj : Loud; |
197 | my LoudDecl @loudobjs : Loud; |
198 | my LoudDecl %loudobjex : Loud; |
199 | |
200 | causes the LoudDecl::Loud handler to be invoked (even if OtherClass also |
201 | defines a handler for ":Loud" attributes). |
202 | |
203 | Type-specific attribute handlers |
204 | If an attribute handler is declared and the ":ATTR" specifier is given |
205 | the name of a built-in type ("SCALAR", "ARRAY", "HASH", or "CODE"), the |
206 | handler is only applied to declarations of that type. For example, the |
207 | following definition: |
208 | |
209 | package LoudDecl; |
210 | |
211 | sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" } |
212 | |
213 | creates an attribute handler that applies only to scalars: |
214 | |
215 | package Painful; |
216 | use base LoudDecl; |
217 | |
218 | my $metal : RealLoud; # invokes &LoudDecl::RealLoud |
219 | my @metal : RealLoud; # error: unknown attribute |
220 | my %metal : RealLoud; # error: unknown attribute |
221 | sub metal : RealLoud {...} # error: unknown attribute |
222 | |
223 | You can, of course, declare separate handlers for these types as well |
224 | (but you'll need to specify "no warnings 'redefine'" to do it quietly): |
225 | |
226 | package LoudDecl; |
227 | use Attribute::Handlers; |
228 | no warnings 'redefine'; |
229 | |
230 | sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" } |
231 | sub RealLoud :ATTR(ARRAY) { print "Urrrrrrrrrr!" } |
232 | sub RealLoud :ATTR(HASH) { print "Arrrrrgggghhhhhh!" } |
233 | sub RealLoud :ATTR(CODE) { croak "Real loud sub torpedoed" } |
234 | |
235 | You can also explicitly indicate that a single handler is meant to be |
236 | used for all types of referents like so: |
237 | |
238 | package LoudDecl; |
239 | use Attribute::Handlers; |
240 | |
241 | sub SeriousLoud :ATTR(ANY) { warn "Hearing loss imminent" } |
242 | |
243 | (I.e. "ATTR(ANY)" is a synonym for ":ATTR"). |
244 | |
245 | Non-interpretive attribute handlers |
246 | Occasionally the strenuous efforts Attribute::Handlers makes to convert |
247 | the data argument ($_[4]) to a useable form before passing it to the |
248 | handler get in the way. |
249 | |
250 | You can turn off that eagerness-to-help by declaring an attribute |
251 | handler with the keyword "RAWDATA". For example: |
252 | |
253 | sub Raw : ATTR(RAWDATA) {...} |
254 | sub Nekkid : ATTR(SCALAR,RAWDATA) {...} |
255 | sub Au::Naturale : ATTR(RAWDATA,ANY) {...} |
256 | |
257 | Then the handler makes absolutely no attempt to interpret the data it |
258 | receives and simply passes it as a string: |
259 | |
260 | my $power : Raw(1..100); # handlers receives "1..100" |
261 | |
262 | Phase-specific attribute handlers |
263 | By default, attribute handlers are called at the end of the compilation |
264 | phase (in a "CHECK" block). This seems to be optimal in most cases |
265 | because most things that can be defined are defined by that point but |
266 | nothing has been executed. |
267 | |
268 | However, it is possible to set up attribute handlers that are called at |
269 | other points in the program's compilation or execution, by explicitly |
270 | stating the phase (or phases) in which you wish the attribute handler to |
271 | be called. For example: |
272 | |
273 | sub Early :ATTR(SCALAR,BEGIN) {...} |
274 | sub Normal :ATTR(SCALAR,CHECK) {...} |
275 | sub Late :ATTR(SCALAR,INIT) {...} |
276 | sub Final :ATTR(SCALAR,END) {...} |
277 | sub Bookends :ATTR(SCALAR,BEGIN,END) {...} |
278 | |
279 | As the last example indicates, a handler may be set up to be (re)called |
280 | in two or more phases. The phase name is passed as the handler's final |
281 | argument. |
282 | |
283 | Note that attribute handlers that are scheduled for the "BEGIN" phase |
284 | are handled as soon as the attribute is detected (i.e. before any |
285 | subsequently defined "BEGIN" blocks are executed). |
286 | |
287 | Attributes as "tie" interfaces |
288 | Attributes make an excellent and intuitive interface through which to |
289 | tie variables. For example: |
290 | |
291 | use Attribute::Handlers; |
292 | use Tie::Cycle; |
293 | |
294 | sub UNIVERSAL::Cycle : ATTR(SCALAR) { |
295 | my ($package, $symbol, $referent, $attr, $data, $phase) = @_; |
296 | $data = [ $data ] unless ref $data eq 'ARRAY'; |
297 | tie $$referent, 'Tie::Cycle', $data; |
298 | } |
299 | |
300 | # and thereafter... |
301 | |
302 | package main; |
303 | |
304 | my $next : Cycle('A'..'Z'); # $next is now a tied variable |
305 | |
306 | while (<>) { |
307 | print $next; |
308 | } |
309 | |
310 | Note that, because the "Cycle" attribute receives its arguments in the |
311 | $data variable, if the attribute is given a list of arguments, $data |
312 | will consist of a single array reference; otherwise, it will consist of |
313 | the single argument directly. Since Tie::Cycle requires its cycling |
314 | values to be passed as an array reference, this means that we need to |
315 | wrap non-array-reference arguments in an array constructor: |
316 | |
317 | $data = [ $data ] unless ref $data eq 'ARRAY'; |
318 | |
319 | Typically, however, things are the other way around: the tieable class |
320 | expects its arguments as a flattened list, so the attribute looks like: |
321 | |
322 | sub UNIVERSAL::Cycle : ATTR(SCALAR) { |
323 | my ($package, $symbol, $referent, $attr, $data, $phase) = @_; |
324 | my @data = ref $data eq 'ARRAY' ? @$data : $data; |
325 | tie $$referent, 'Tie::Whatever', @data; |
326 | } |
327 | |
328 | This software pattern is so widely applicable that Attribute::Handlers |
329 | provides a way to automate it: specifying 'autotie' in the "use |
330 | Attribute::Handlers" statement. So, the cycling example, could also be |
331 | written: |
332 | |
333 | use Attribute::Handlers autotie => { Cycle => 'Tie::Cycle' }; |
334 | |
335 | # and thereafter... |
336 | |
337 | package main; |
338 | |
339 | my $next : Cycle(['A'..'Z']); # $next is now a tied variable |
340 | |
341 | while (<>) { |
342 | print $next; |
343 | |
344 | Note that we now have to pass the cycling values as an array reference, |
345 | since the "autotie" mechanism passes "tie" a list of arguments as a list |
346 | (as in the Tie::Whatever example), *not* as an array reference (as in |
347 | the original Tie::Cycle example at the start of this section). |
348 | |
349 | The argument after 'autotie' is a reference to a hash in which each key |
350 | is the name of an attribute to be created, and each value is the class |
351 | to which variables ascribed that attribute should be tied. |
352 | |
353 | Note that there is no longer any need to import the Tie::Cycle module -- |
354 | Attribute::Handlers takes care of that automagically. You can even pass |
355 | arguments to the module's "import" subroutine, by appending them to the |
356 | class name. For example: |
357 | |
358 | use Attribute::Handlers |
359 | autotie => { Dir => 'Tie::Dir qw(DIR_UNLINK)' }; |
360 | |
361 | If the attribute name is unqualified, the attribute is installed in the |
362 | current package. Otherwise it is installed in the qualifier's package: |
363 | |
364 | package Here; |
365 | |
366 | use Attribute::Handlers autotie => { |
367 | Other::Good => Tie::SecureHash, # tie attr installed in Other:: |
368 | Bad => Tie::Taxes, # tie attr installed in Here:: |
369 | UNIVERSAL::Ugly => Software::Patent # tie attr installed everywhere |
370 | }; |
371 | |
372 | Autoties are most commonly used in the module to which they actually |
373 | tie, and need to export their attributes to any module that calls them. |
374 | To facilitate this, Attribute::Handlers recognizes a special |
375 | "pseudo-class" -- "__CALLER__", which may be specified as the qualifier |
376 | of an attribute: |
377 | |
378 | package Tie::Me::Kangaroo:Down::Sport; |
379 | |
380 | use Attribute::Handlers autotie => { '__CALLER__::Roo' => __PACKAGE__ }; |
381 | |
382 | This causes Attribute::Handlers to define the "Roo" attribute in the |
383 | package that imports the Tie::Me::Kangaroo:Down::Sport module. |
384 | |
385 | Note that it is important to quote the __CALLER__::Roo identifier |
386 | because a bug in perl 5.8 will refuse to parse it and cause an unknown |
387 | error. |
388 | |
389 | Passing the tied object to "tie" |
390 | Occasionally it is important to pass a reference to the object being |
391 | tied to the TIESCALAR, TIEHASH, etc. that ties it. |
392 | |
393 | The "autotie" mechanism supports this too. The following code: |
394 | |
395 | use Attribute::Handlers autotieref => { Selfish => Tie::Selfish }; |
396 | my $var : Selfish(@args); |
397 | |
398 | has the same effect as: |
399 | |
400 | tie my $var, 'Tie::Selfish', @args; |
401 | |
402 | But when "autotieref" is used instead of "autotie": |
403 | |
404 | use Attribute::Handlers autotieref => { Selfish => Tie::Selfish }; |
405 | my $var : Selfish(@args); |
406 | |
407 | the effect is to pass the "tie" call an extra reference to the variable |
408 | being tied: |
409 | |
410 | tie my $var, 'Tie::Selfish', \$var, @args; |
411 | |
412 | EXAMPLES |
413 | If the class shown in SYNOPSIS were placed in the MyClass.pm module, |
414 | then the following code: |
415 | |
416 | package main; |
417 | use MyClass; |
418 | |
419 | my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous); |
420 | |
421 | package SomeOtherClass; |
422 | use base MyClass; |
423 | |
424 | sub tent { 'acle' } |
425 | |
426 | sub fn :Ugly(sister) :Omni('po',tent()) {...} |
427 | my @arr :Good :Omni(s/cie/nt/); |
428 | my %hsh :Good(q/bye/) :Omni(q/bus/); |
429 | |
430 | would cause the following handlers to be invoked: |
431 | |
432 | # my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous); |
433 | |
434 | MyClass::Good:ATTR(SCALAR)( 'MyClass', # class |
435 | 'LEXICAL', # no typeglob |
436 | \$slr, # referent |
437 | 'Good', # attr name |
438 | undef # no attr data |
439 | 'CHECK', # compiler phase |
440 | ); |
441 | |
442 | MyClass::Bad:ATTR(SCALAR)( 'MyClass', # class |
443 | 'LEXICAL', # no typeglob |
444 | \$slr, # referent |
445 | 'Bad', # attr name |
446 | 0 # eval'd attr data |
447 | 'CHECK', # compiler phase |
448 | ); |
449 | |
450 | MyClass::Omni:ATTR(SCALAR)( 'MyClass', # class |
451 | 'LEXICAL', # no typeglob |
452 | \$slr, # referent |
453 | 'Omni', # attr name |
454 | '-vorous' # eval'd attr data |
455 | 'CHECK', # compiler phase |
456 | ); |
457 | |
458 | |
459 | # sub fn :Ugly(sister) :Omni('po',tent()) {...} |
460 | |
461 | MyClass::UGLY:ATTR(CODE)( 'SomeOtherClass', # class |
462 | \*SomeOtherClass::fn, # typeglob |
463 | \&SomeOtherClass::fn, # referent |
464 | 'Ugly', # attr name |
465 | 'sister' # eval'd attr data |
466 | 'CHECK', # compiler phase |
467 | ); |
468 | |
469 | MyClass::Omni:ATTR(CODE)( 'SomeOtherClass', # class |
470 | \*SomeOtherClass::fn, # typeglob |
471 | \&SomeOtherClass::fn, # referent |
472 | 'Omni', # attr name |
473 | ['po','acle'] # eval'd attr data |
474 | 'CHECK', # compiler phase |
475 | ); |
476 | |
477 | |
478 | # my @arr :Good :Omni(s/cie/nt/); |
479 | |
480 | MyClass::Good:ATTR(ARRAY)( 'SomeOtherClass', # class |
481 | 'LEXICAL', # no typeglob |
482 | \@arr, # referent |
483 | 'Good', # attr name |
484 | undef # no attr data |
485 | 'CHECK', # compiler phase |
486 | ); |
487 | |
488 | MyClass::Omni:ATTR(ARRAY)( 'SomeOtherClass', # class |
489 | 'LEXICAL', # no typeglob |
490 | \@arr, # referent |
491 | 'Omni', # attr name |
492 | "" # eval'd attr data |
493 | 'CHECK', # compiler phase |
494 | ); |
495 | |
496 | |
497 | # my %hsh :Good(q/bye) :Omni(q/bus/); |
498 | |
499 | MyClass::Good:ATTR(HASH)( 'SomeOtherClass', # class |
500 | 'LEXICAL', # no typeglob |
501 | \%hsh, # referent |
502 | 'Good', # attr name |
503 | 'q/bye' # raw attr data |
504 | 'CHECK', # compiler phase |
505 | ); |
506 | |
507 | MyClass::Omni:ATTR(HASH)( 'SomeOtherClass', # class |
508 | 'LEXICAL', # no typeglob |
509 | \%hsh, # referent |
510 | 'Omni', # attr name |
511 | 'bus' # eval'd attr data |
512 | 'CHECK', # compiler phase |
513 | ); |
514 | |
515 | Installing handlers into UNIVERSAL, makes them...err..universal. For |
516 | example: |
517 | |
518 | package Descriptions; |
519 | use Attribute::Handlers; |
520 | |
521 | my %name; |
522 | sub name { return $name{$_[2]}||*{$_[1]}{NAME} } |
523 | |
524 | sub UNIVERSAL::Name :ATTR { |
525 | $name{$_[2]} = $_[4]; |
526 | } |
527 | |
528 | sub UNIVERSAL::Purpose :ATTR { |
529 | print STDERR "Purpose of ", &name, " is $_[4]\n"; |
530 | } |
531 | |
532 | sub UNIVERSAL::Unit :ATTR { |
533 | print STDERR &name, " measured in $_[4]\n"; |
534 | } |
535 | |
536 | Let's you write: |
537 | |
538 | use Descriptions; |
539 | |
540 | my $capacity : Name(capacity) |
541 | : Purpose(to store max storage capacity for files) |
542 | : Unit(Gb); |
543 | |
544 | |
545 | package Other; |
546 | |
547 | sub foo : Purpose(to foo all data before barring it) { } |
548 | |
549 | # etc. |
550 | |
551 | DIAGNOSTICS |
552 | "Bad attribute type: ATTR(%s)" |
553 | An attribute handler was specified with an ":ATTR(*ref_type*)", but |
554 | the type of referent it was defined to handle wasn't one of the five |
555 | permitted: "SCALAR", "ARRAY", "HASH", "CODE", or "ANY". |
556 | |
557 | "Attribute handler %s doesn't handle %s attributes" |
558 | A handler for attributes of the specified name *was* defined, but |
559 | not for the specified type of declaration. Typically encountered whe |
560 | trying to apply a "VAR" attribute handler to a subroutine, or a |
561 | "SCALAR" attribute handler to some other type of variable. |
562 | |
563 | "Declaration of %s attribute in package %s may clash with future |
564 | reserved word" |
565 | A handler for an attributes with an all-lowercase name was declared. |
566 | An attribute with an all-lowercase name might have a meaning to Perl |
567 | itself some day, even though most don't yet. Use a mixed-case |
568 | attribute name, instead. |
569 | |
570 | "Can't have two ATTR specifiers on one subroutine" |
571 | You just can't, okay? Instead, put all the specifications together |
572 | with commas between them in a single "ATTR(*specification*)". |
573 | |
574 | "Can't autotie a %s" |
575 | You can only declare autoties for types "SCALAR", "ARRAY", and |
576 | "HASH". They're the only things (apart from typeglobs -- which are |
577 | not declarable) that Perl can tie. |
578 | |
579 | "Internal error: %s symbol went missing" |
580 | Something is rotten in the state of the program. An attributed |
581 | subroutine ceased to exist between the point it was declared and the |
582 | point at which its attribute handler(s) would have been called. |
583 | |
584 | "Won't be able to apply END handler" |
585 | You have defined an END handler for an attribute that is being |
586 | applied to a lexical variable. Since the variable may not be |
587 | available during END this won't happen. |
588 | |
589 | AUTHOR |
590 | Damian Conway (damian@conway.org). The maintainer of this module is now |
591 | Rafael Garcia-Suarez (rgarciasuarez@gmail.com). |
592 | |
593 | Maintainer of the CPAN release is Steffen Mueller (smueller@cpan.org). |
594 | Contact him with technical difficulties with respect to the packaging of |
595 | the CPAN module. |
596 | |
597 | BUGS |
598 | There are undoubtedly serious bugs lurking somewhere in code this funky |
599 | :-) Bug reports and other feedback are most welcome. |
600 | |
601 | COPYRIGHT AND LICENSE |
602 | Copyright (c) 2001-2009, Damian Conway. All Rights Reserved. |
603 | This module is free software. It may be used, redistributed |
604 | and/or modified under the same terms as Perl itself. |
0e9b9e0c |
605 | |