Commit | Line | Data |
3fea05b9 |
1 | .\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.3 |
2 | .\" |
3 | .\" Standard preamble: |
4 | .\" ======================================================================== |
5 | .de Sh \" Subsection heading |
6 | .br |
7 | .if t .Sp |
8 | .ne 5 |
9 | .PP |
10 | \fB\\$1\fR |
11 | .PP |
12 | .. |
13 | .de Sp \" Vertical space (when we can't use .PP) |
14 | .if t .sp .5v |
15 | .if n .sp |
16 | .. |
17 | .de Vb \" Begin verbatim text |
18 | .ft CW |
19 | .nf |
20 | .ne \\$1 |
21 | .. |
22 | .de Ve \" End verbatim text |
23 | .ft R |
24 | .fi |
25 | .. |
26 | .\" Set up some character translations and predefined strings. \*(-- will |
27 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left |
28 | .\" double quote, and \*(R" will give a right double quote. | will give a |
29 | .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to |
30 | .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' |
31 | .\" expand to `' in nroff, nothing in troff, for use with C<>. |
32 | .tr \(*W-|\(bv\*(Tr |
33 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' |
34 | .ie n \{\ |
35 | . ds -- \(*W- |
36 | . ds PI pi |
37 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch |
38 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch |
39 | . ds L" "" |
40 | . ds R" "" |
41 | . ds C` "" |
42 | . ds C' "" |
43 | 'br\} |
44 | .el\{\ |
45 | . ds -- \|\(em\| |
46 | . ds PI \(*p |
47 | . ds L" `` |
48 | . ds R" '' |
49 | 'br\} |
50 | .\" |
51 | .\" If the F register is turned on, we'll generate index entries on stderr for |
52 | .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index |
53 | .\" entries marked with X<> in POD. Of course, you'll have to process the |
54 | .\" output yourself in some meaningful fashion. |
55 | .if \nF \{\ |
56 | . de IX |
57 | . tm Index:\\$1\t\\n%\t"\\$2" |
58 | .. |
59 | . nr % 0 |
60 | . rr F |
61 | .\} |
62 | .\" |
63 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes |
64 | .\" way too many mistakes in technical documents. |
65 | .hy 0 |
66 | .if n .na |
67 | .\" |
68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). |
69 | .\" Fear. Run. Save yourself. No user-serviceable parts. |
70 | . \" fudge factors for nroff and troff |
71 | .if n \{\ |
72 | . ds #H 0 |
73 | . ds #V .8m |
74 | . ds #F .3m |
75 | . ds #[ \f1 |
76 | . ds #] \fP |
77 | .\} |
78 | .if t \{\ |
79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) |
80 | . ds #V .6m |
81 | . ds #F 0 |
82 | . ds #[ \& |
83 | . ds #] \& |
84 | .\} |
85 | . \" simple accents for nroff and troff |
86 | .if n \{\ |
87 | . ds ' \& |
88 | . ds ` \& |
89 | . ds ^ \& |
90 | . ds , \& |
91 | . ds ~ ~ |
92 | . ds / |
93 | .\} |
94 | .if t \{\ |
95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" |
96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' |
97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' |
98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' |
99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' |
100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' |
101 | .\} |
102 | . \" troff and (daisy-wheel) nroff accents |
103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' |
104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' |
105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] |
106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' |
107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' |
108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] |
109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] |
110 | .ds ae a\h'-(\w'a'u*4/10)'e |
111 | .ds Ae A\h'-(\w'A'u*4/10)'E |
112 | . \" corrections for vroff |
113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' |
114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' |
115 | . \" for low resolution devices (crt and lpr) |
116 | .if \n(.H>23 .if \n(.V>19 \ |
117 | \{\ |
118 | . ds : e |
119 | . ds 8 ss |
120 | . ds o a |
121 | . ds d- d\h'-1'\(ga |
122 | . ds D- D\h'-1'\(hy |
123 | . ds th \o'bp' |
124 | . ds Th \o'LP' |
125 | . ds ae ae |
126 | . ds Ae AE |
127 | .\} |
128 | .rm #[ #] #H #V #F C |
129 | .\" ======================================================================== |
130 | .\" |
131 | .IX Title "Attribute::Handlers 3" |
132 | .TH Attribute::Handlers 3 "2009-09-21" "perl v5.8.7" "User Contributed Perl Documentation" |
133 | .SH "NAME" |
134 | Attribute::Handlers \- Simpler definition of attribute handlers |
135 | .SH "VERSION" |
136 | .IX Header "VERSION" |
137 | This document describes version 0.87 of Attribute::Handlers, |
138 | released September 21, 2009. |
139 | .SH "SYNOPSIS" |
140 | .IX Header "SYNOPSIS" |
141 | .Vb 4 |
142 | \& package MyClass; |
143 | \& require 5.006; |
144 | \& use Attribute::Handlers; |
145 | \& no warnings 'redefine'; |
146 | .Ve |
147 | .PP |
148 | .Vb 2 |
149 | \& sub Good : ATTR(SCALAR) { |
150 | \& my ($package, $symbol, $referent, $attr, $data) = @_; |
151 | .Ve |
152 | .PP |
153 | .Vb 3 |
154 | \& # Invoked for any scalar variable with a :Good attribute, |
155 | \& # provided the variable was declared in MyClass (or |
156 | \& # a derived class) or typed to MyClass. |
157 | .Ve |
158 | .PP |
159 | .Vb 3 |
160 | \& # Do whatever to $referent here (executed in CHECK phase). |
161 | \& ... |
162 | \& } |
163 | .Ve |
164 | .PP |
165 | .Vb 6 |
166 | \& sub Bad : ATTR(SCALAR) { |
167 | \& # Invoked for any scalar variable with a :Bad attribute, |
168 | \& # provided the variable was declared in MyClass (or |
169 | \& # a derived class) or typed to MyClass. |
170 | \& ... |
171 | \& } |
172 | .Ve |
173 | .PP |
174 | .Vb 6 |
175 | \& sub Good : ATTR(ARRAY) { |
176 | \& # Invoked for any array variable with a :Good attribute, |
177 | \& # provided the variable was declared in MyClass (or |
178 | \& # a derived class) or typed to MyClass. |
179 | \& ... |
180 | \& } |
181 | .Ve |
182 | .PP |
183 | .Vb 6 |
184 | \& sub Good : ATTR(HASH) { |
185 | \& # Invoked for any hash variable with a :Good attribute, |
186 | \& # provided the variable was declared in MyClass (or |
187 | \& # a derived class) or typed to MyClass. |
188 | \& ... |
189 | \& } |
190 | .Ve |
191 | .PP |
192 | .Vb 5 |
193 | \& sub Ugly : ATTR(CODE) { |
194 | \& # Invoked for any subroutine declared in MyClass (or a |
195 | \& # derived class) with an :Ugly attribute. |
196 | \& ... |
197 | \& } |
198 | .Ve |
199 | .PP |
200 | .Vb 8 |
201 | \& sub Omni : ATTR { |
202 | \& # Invoked for any scalar, array, hash, or subroutine |
203 | \& # with an :Omni attribute, provided the variable or |
204 | \& # subroutine was declared in MyClass (or a derived class) |
205 | \& # or the variable was typed to MyClass. |
206 | \& # Use ref($_[2]) to determine what kind of referent it was. |
207 | \& ... |
208 | \& } |
209 | .Ve |
210 | .PP |
211 | .Vb 1 |
212 | \& use Attribute::Handlers autotie => { Cycle => Tie::Cycle }; |
213 | .Ve |
214 | .PP |
215 | .Vb 1 |
216 | \& my $next : Cycle(['A'..'Z']); |
217 | .Ve |
218 | .SH "DESCRIPTION" |
219 | .IX Header "DESCRIPTION" |
220 | This module, when inherited by a package, allows that package's class to |
221 | define attribute handler subroutines for specific attributes. Variables |
222 | and subroutines subsequently defined in that package, or in packages |
223 | derived from that package may be given attributes with the same names as |
224 | the attribute handler subroutines, which will then be called in one of |
225 | the compilation phases (i.e. in a \f(CW\*(C`BEGIN\*(C'\fR, \f(CW\*(C`CHECK\*(C'\fR, \f(CW\*(C`INIT\*(C'\fR, or \f(CW\*(C`END\*(C'\fR |
226 | block). (\f(CW\*(C`UNITCHECK\*(C'\fR blocks don't correspond to a global compilation |
227 | phase, so they can't be specified here.) |
228 | .PP |
229 | To create a handler, define it as a subroutine with the same name as |
230 | the desired attribute, and declare the subroutine itself with the |
231 | attribute \f(CW\*(C`:ATTR\*(C'\fR. For example: |
232 | .PP |
233 | .Vb 2 |
234 | \& package LoudDecl; |
235 | \& use Attribute::Handlers; |
236 | .Ve |
237 | .PP |
238 | .Vb 11 |
239 | \& sub Loud :ATTR { |
240 | \& my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = @_; |
241 | \& print STDERR |
242 | \& ref($referent), " ", |
243 | \& *{$symbol}{NAME}, " ", |
244 | \& "($referent) ", "was just declared ", |
245 | \& "and ascribed the ${attr} attribute ", |
246 | \& "with data ($data)\en", |
247 | \& "in phase $phase\en", |
248 | \& "in file $filename at line $linenum\en"; |
249 | \& } |
250 | .Ve |
251 | .PP |
252 | This creates a handler for the attribute \f(CW\*(C`:Loud\*(C'\fR in the class LoudDecl. |
253 | Thereafter, any subroutine declared with a \f(CW\*(C`:Loud\*(C'\fR attribute in the class |
254 | LoudDecl: |
255 | .PP |
256 | .Vb 1 |
257 | \& package LoudDecl; |
258 | .Ve |
259 | .PP |
260 | .Vb 1 |
261 | \& sub foo: Loud {...} |
262 | .Ve |
263 | .PP |
264 | causes the above handler to be invoked, and passed: |
265 | .IP "[0]" 4 |
266 | .IX Item "[0]" |
267 | the name of the package into which it was declared; |
268 | .IP "[1]" 4 |
269 | .IX Item "[1]" |
270 | a reference to the symbol table entry (typeglob) containing the subroutine; |
271 | .IP "[2]" 4 |
272 | .IX Item "[2]" |
273 | a reference to the subroutine; |
274 | .IP "[3]" 4 |
275 | .IX Item "[3]" |
276 | the name of the attribute; |
277 | .IP "[4]" 4 |
278 | .IX Item "[4]" |
279 | any data associated with that attribute; |
280 | .IP "[5]" 4 |
281 | .IX Item "[5]" |
282 | the name of the phase in which the handler is being invoked; |
283 | .IP "[6]" 4 |
284 | .IX Item "[6]" |
285 | the filename in which the handler is being invoked; |
286 | .IP "[7]" 4 |
287 | .IX Item "[7]" |
288 | the line number in this file. |
289 | .PP |
290 | Likewise, declaring any variables with the \f(CW\*(C`:Loud\*(C'\fR attribute within the |
291 | package: |
292 | .PP |
293 | .Vb 1 |
294 | \& package LoudDecl; |
295 | .Ve |
296 | .PP |
297 | .Vb 3 |
298 | \& my $foo :Loud; |
299 | \& my @foo :Loud; |
300 | \& my %foo :Loud; |
301 | .Ve |
302 | .PP |
303 | will cause the handler to be called with a similar argument list (except, |
304 | of course, that \f(CW$_[2]\fR will be a reference to the variable). |
305 | .PP |
306 | The package name argument will typically be the name of the class into |
307 | which the subroutine was declared, but it may also be the name of a derived |
308 | class (since handlers are inherited). |
309 | .PP |
310 | If a lexical variable is given an attribute, there is no symbol table to |
311 | which it belongs, so the symbol table argument (\f(CW$_[1]\fR) is set to the |
312 | string \f(CW'LEXICAL'\fR in that case. Likewise, ascribing an attribute to |
313 | an anonymous subroutine results in a symbol table argument of \f(CW'ANON'\fR. |
314 | .PP |
315 | The data argument passes in the value (if any) associated with the |
316 | attribute. For example, if \f(CW&foo\fR had been declared: |
317 | .PP |
318 | .Vb 1 |
319 | \& sub foo :Loud("turn it up to 11, man!") {...} |
320 | .Ve |
321 | .PP |
322 | then a reference to an array containing the string |
323 | \&\f(CW"turn it up to 11, man!"\fR would be passed as the last argument. |
324 | .PP |
325 | Attribute::Handlers makes strenuous efforts to convert |
326 | the data argument (\f(CW$_[4]\fR) to a useable form before passing it to |
327 | the handler (but see \*(L"Non\-interpretive attribute handlers\*(R"). |
328 | If those efforts succeed, the interpreted data is passed in an array |
329 | reference; if they fail, the raw data is passed as a string. |
330 | For example, all of these: |
331 | .PP |
332 | .Vb 4 |
333 | \& sub foo :Loud(till=>ears=>are=>bleeding) {...} |
334 | \& sub foo :Loud(qw/till ears are bleeding/) {...} |
335 | \& sub foo :Loud(qw/my, ears, are, bleeding/) {...} |
336 | \& sub foo :Loud(till,ears,are,bleeding) {...} |
337 | .Ve |
338 | .PP |
339 | causes it to pass \f(CW\*(C`['till','ears','are','bleeding']\*(C'\fR as the handler's |
340 | data argument. While: |
341 | .PP |
342 | .Vb 1 |
343 | \& sub foo :Loud(['till','ears','are','bleeding']) {...} |
344 | .Ve |
345 | .PP |
346 | causes it to pass \f(CW\*(C`[ ['till','ears','are','bleeding'] ]\*(C'\fR; the array |
347 | reference specified in the data being passed inside the standard |
348 | array reference indicating successful interpretation. |
349 | .PP |
350 | However, if the data can't be parsed as valid Perl, then |
351 | it is passed as an uninterpreted string. For example: |
352 | .PP |
353 | .Vb 2 |
354 | \& sub foo :Loud(my,ears,are,bleeding) {...} |
355 | \& sub foo :Loud(qw/my ears are bleeding) {...} |
356 | .Ve |
357 | .PP |
358 | cause the strings \f(CW'my,ears,are,bleeding'\fR and |
359 | \&\f(CW'qw/my ears are bleeding'\fR respectively to be passed as the |
360 | data argument. |
361 | .PP |
362 | If no value is associated with the attribute, \f(CW\*(C`undef\*(C'\fR is passed. |
363 | .Sh "Typed lexicals" |
364 | .IX Subsection "Typed lexicals" |
365 | Regardless of the package in which it is declared, if a lexical variable is |
366 | ascribed an attribute, the handler that is invoked is the one belonging to |
367 | the package to which it is typed. For example, the following declarations: |
368 | .PP |
369 | .Vb 1 |
370 | \& package OtherClass; |
371 | .Ve |
372 | .PP |
373 | .Vb 3 |
374 | \& my LoudDecl $loudobj : Loud; |
375 | \& my LoudDecl @loudobjs : Loud; |
376 | \& my LoudDecl %loudobjex : Loud; |
377 | .Ve |
378 | .PP |
379 | causes the LoudDecl::Loud handler to be invoked (even if OtherClass also |
380 | defines a handler for \f(CW\*(C`:Loud\*(C'\fR attributes). |
381 | .Sh "Type-specific attribute handlers" |
382 | .IX Subsection "Type-specific attribute handlers" |
383 | If an attribute handler is declared and the \f(CW\*(C`:ATTR\*(C'\fR specifier is |
384 | given the name of a built-in type (\f(CW\*(C`SCALAR\*(C'\fR, \f(CW\*(C`ARRAY\*(C'\fR, \f(CW\*(C`HASH\*(C'\fR, or \f(CW\*(C`CODE\*(C'\fR), |
385 | the handler is only applied to declarations of that type. For example, |
386 | the following definition: |
387 | .PP |
388 | .Vb 1 |
389 | \& package LoudDecl; |
390 | .Ve |
391 | .PP |
392 | .Vb 1 |
393 | \& sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" } |
394 | .Ve |
395 | .PP |
396 | creates an attribute handler that applies only to scalars: |
397 | .PP |
398 | .Vb 2 |
399 | \& package Painful; |
400 | \& use base LoudDecl; |
401 | .Ve |
402 | .PP |
403 | .Vb 4 |
404 | \& my $metal : RealLoud; # invokes &LoudDecl::RealLoud |
405 | \& my @metal : RealLoud; # error: unknown attribute |
406 | \& my %metal : RealLoud; # error: unknown attribute |
407 | \& sub metal : RealLoud {...} # error: unknown attribute |
408 | .Ve |
409 | .PP |
410 | You can, of course, declare separate handlers for these types as well |
411 | (but you'll need to specify \f(CW\*(C`no warnings 'redefine'\*(C'\fR to do it quietly): |
412 | .PP |
413 | .Vb 3 |
414 | \& package LoudDecl; |
415 | \& use Attribute::Handlers; |
416 | \& no warnings 'redefine'; |
417 | .Ve |
418 | .PP |
419 | .Vb 4 |
420 | \& sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" } |
421 | \& sub RealLoud :ATTR(ARRAY) { print "Urrrrrrrrrr!" } |
422 | \& sub RealLoud :ATTR(HASH) { print "Arrrrrgggghhhhhh!" } |
423 | \& sub RealLoud :ATTR(CODE) { croak "Real loud sub torpedoed" } |
424 | .Ve |
425 | .PP |
426 | You can also explicitly indicate that a single handler is meant to be |
427 | used for all types of referents like so: |
428 | .PP |
429 | .Vb 2 |
430 | \& package LoudDecl; |
431 | \& use Attribute::Handlers; |
432 | .Ve |
433 | .PP |
434 | .Vb 1 |
435 | \& sub SeriousLoud :ATTR(ANY) { warn "Hearing loss imminent" } |
436 | .Ve |
437 | .PP |
438 | (I.e. \f(CW\*(C`ATTR(ANY)\*(C'\fR is a synonym for \f(CW\*(C`:ATTR\*(C'\fR). |
439 | .Sh "Non-interpretive attribute handlers" |
440 | .IX Subsection "Non-interpretive attribute handlers" |
441 | Occasionally the strenuous efforts Attribute::Handlers makes to convert |
442 | the data argument (\f(CW$_[4]\fR) to a useable form before passing it to |
443 | the handler get in the way. |
444 | .PP |
445 | You can turn off that eagerness-to-help by declaring |
446 | an attribute handler with the keyword \f(CW\*(C`RAWDATA\*(C'\fR. For example: |
447 | .PP |
448 | .Vb 3 |
449 | \& sub Raw : ATTR(RAWDATA) {...} |
450 | \& sub Nekkid : ATTR(SCALAR,RAWDATA) {...} |
451 | \& sub Au::Naturale : ATTR(RAWDATA,ANY) {...} |
452 | .Ve |
453 | .PP |
454 | Then the handler makes absolutely no attempt to interpret the data it |
455 | receives and simply passes it as a string: |
456 | .PP |
457 | .Vb 1 |
458 | \& my $power : Raw(1..100); # handlers receives "1..100" |
459 | .Ve |
460 | .Sh "Phase-specific attribute handlers" |
461 | .IX Subsection "Phase-specific attribute handlers" |
462 | By default, attribute handlers are called at the end of the compilation |
463 | phase (in a \f(CW\*(C`CHECK\*(C'\fR block). This seems to be optimal in most cases because |
464 | most things that can be defined are defined by that point but nothing has |
465 | been executed. |
466 | .PP |
467 | However, it is possible to set up attribute handlers that are called at |
468 | other points in the program's compilation or execution, by explicitly |
469 | stating the phase (or phases) in which you wish the attribute handler to |
470 | be called. For example: |
471 | .PP |
472 | .Vb 5 |
473 | \& sub Early :ATTR(SCALAR,BEGIN) {...} |
474 | \& sub Normal :ATTR(SCALAR,CHECK) {...} |
475 | \& sub Late :ATTR(SCALAR,INIT) {...} |
476 | \& sub Final :ATTR(SCALAR,END) {...} |
477 | \& sub Bookends :ATTR(SCALAR,BEGIN,END) {...} |
478 | .Ve |
479 | .PP |
480 | As the last example indicates, a handler may be set up to be (re)called in |
481 | two or more phases. The phase name is passed as the handler's final argument. |
482 | .PP |
483 | Note that attribute handlers that are scheduled for the \f(CW\*(C`BEGIN\*(C'\fR phase |
484 | are handled as soon as the attribute is detected (i.e. before any |
485 | subsequently defined \f(CW\*(C`BEGIN\*(C'\fR blocks are executed). |
486 | .ie n .Sh "Attributes as ""tie"" interfaces" |
487 | .el .Sh "Attributes as \f(CWtie\fP interfaces" |
488 | .IX Subsection "Attributes as tie interfaces" |
489 | Attributes make an excellent and intuitive interface through which to tie |
490 | variables. For example: |
491 | .PP |
492 | .Vb 2 |
493 | \& use Attribute::Handlers; |
494 | \& use Tie::Cycle; |
495 | .Ve |
496 | .PP |
497 | .Vb 5 |
498 | \& sub UNIVERSAL::Cycle : ATTR(SCALAR) { |
499 | \& my ($package, $symbol, $referent, $attr, $data, $phase) = @_; |
500 | \& $data = [ $data ] unless ref $data eq 'ARRAY'; |
501 | \& tie $$referent, 'Tie::Cycle', $data; |
502 | \& } |
503 | .Ve |
504 | .PP |
505 | .Vb 1 |
506 | \& # and thereafter... |
507 | .Ve |
508 | .PP |
509 | .Vb 1 |
510 | \& package main; |
511 | .Ve |
512 | .PP |
513 | .Vb 1 |
514 | \& my $next : Cycle('A'..'Z'); # $next is now a tied variable |
515 | .Ve |
516 | .PP |
517 | .Vb 3 |
518 | \& while (<>) { |
519 | \& print $next; |
520 | \& } |
521 | .Ve |
522 | .PP |
523 | Note that, because the \f(CW\*(C`Cycle\*(C'\fR attribute receives its arguments in the |
524 | \&\f(CW$data\fR variable, if the attribute is given a list of arguments, \f(CW$data\fR |
525 | will consist of a single array reference; otherwise, it will consist of the |
526 | single argument directly. Since Tie::Cycle requires its cycling values to |
527 | be passed as an array reference, this means that we need to wrap |
528 | non-array-reference arguments in an array constructor: |
529 | .PP |
530 | .Vb 1 |
531 | \& $data = [ $data ] unless ref $data eq 'ARRAY'; |
532 | .Ve |
533 | .PP |
534 | Typically, however, things are the other way around: the tieable class expects |
535 | its arguments as a flattened list, so the attribute looks like: |
536 | .PP |
537 | .Vb 5 |
538 | \& sub UNIVERSAL::Cycle : ATTR(SCALAR) { |
539 | \& my ($package, $symbol, $referent, $attr, $data, $phase) = @_; |
540 | \& my @data = ref $data eq 'ARRAY' ? @$data : $data; |
541 | \& tie $$referent, 'Tie::Whatever', @data; |
542 | \& } |
543 | .Ve |
544 | .PP |
545 | This software pattern is so widely applicable that Attribute::Handlers |
546 | provides a way to automate it: specifying \f(CW'autotie'\fR in the |
547 | \&\f(CW\*(C`use Attribute::Handlers\*(C'\fR statement. So, the cycling example, |
548 | could also be written: |
549 | .PP |
550 | .Vb 1 |
551 | \& use Attribute::Handlers autotie => { Cycle => 'Tie::Cycle' }; |
552 | .Ve |
553 | .PP |
554 | .Vb 1 |
555 | \& # and thereafter... |
556 | .Ve |
557 | .PP |
558 | .Vb 1 |
559 | \& package main; |
560 | .Ve |
561 | .PP |
562 | .Vb 1 |
563 | \& my $next : Cycle(['A'..'Z']); # $next is now a tied variable |
564 | .Ve |
565 | .PP |
566 | .Vb 2 |
567 | \& while (<>) { |
568 | \& print $next; |
569 | .Ve |
570 | .PP |
571 | Note that we now have to pass the cycling values as an array reference, |
572 | since the \f(CW\*(C`autotie\*(C'\fR mechanism passes \f(CW\*(C`tie\*(C'\fR a list of arguments as a list |
573 | (as in the Tie::Whatever example), \fInot\fR as an array reference (as in |
574 | the original Tie::Cycle example at the start of this section). |
575 | .PP |
576 | The argument after \f(CW'autotie'\fR is a reference to a hash in which each key is |
577 | the name of an attribute to be created, and each value is the class to which |
578 | variables ascribed that attribute should be tied. |
579 | .PP |
580 | Note that there is no longer any need to import the Tie::Cycle module \*(-- |
581 | Attribute::Handlers takes care of that automagically. You can even pass |
582 | arguments to the module's \f(CW\*(C`import\*(C'\fR subroutine, by appending them to the |
583 | class name. For example: |
584 | .PP |
585 | .Vb 2 |
586 | \& use Attribute::Handlers |
587 | \& autotie => { Dir => 'Tie::Dir qw(DIR_UNLINK)' }; |
588 | .Ve |
589 | .PP |
590 | If the attribute name is unqualified, the attribute is installed in the |
591 | current package. Otherwise it is installed in the qualifier's package: |
592 | .PP |
593 | .Vb 1 |
594 | \& package Here; |
595 | .Ve |
596 | .PP |
597 | .Vb 5 |
598 | \& use Attribute::Handlers autotie => { |
599 | \& Other::Good => Tie::SecureHash, # tie attr installed in Other:: |
600 | \& Bad => Tie::Taxes, # tie attr installed in Here:: |
601 | \& UNIVERSAL::Ugly => Software::Patent # tie attr installed everywhere |
602 | \& }; |
603 | .Ve |
604 | .PP |
605 | Autoties are most commonly used in the module to which they actually tie, |
606 | and need to export their attributes to any module that calls them. To |
607 | facilitate this, Attribute::Handlers recognizes a special \*(L"pseudo\-class\*(R" \*(-- |
608 | \&\f(CW\*(C`_\|_CALLER_\|_\*(C'\fR, which may be specified as the qualifier of an attribute: |
609 | .PP |
610 | .Vb 1 |
611 | \& package Tie::Me::Kangaroo:Down::Sport; |
612 | .Ve |
613 | .PP |
614 | .Vb 1 |
615 | \& use Attribute::Handlers autotie => { '__CALLER__::Roo' => __PACKAGE__ }; |
616 | .Ve |
617 | .PP |
618 | This causes Attribute::Handlers to define the \f(CW\*(C`Roo\*(C'\fR attribute in the package |
619 | that imports the Tie::Me::Kangaroo:Down::Sport module. |
620 | .PP |
621 | Note that it is important to quote the _\|_CALLER_\|_::Roo identifier because |
622 | a bug in perl 5.8 will refuse to parse it and cause an unknown error. |
623 | .PP |
624 | \fIPassing the tied object to \f(CI\*(C`tie\*(C'\fI\fR |
625 | .IX Subsection "Passing the tied object to tie" |
626 | .PP |
627 | Occasionally it is important to pass a reference to the object being tied |
628 | to the \s-1TIESCALAR\s0, \s-1TIEHASH\s0, etc. that ties it. |
629 | .PP |
630 | The \f(CW\*(C`autotie\*(C'\fR mechanism supports this too. The following code: |
631 | .PP |
632 | .Vb 2 |
633 | \& use Attribute::Handlers autotieref => { Selfish => Tie::Selfish }; |
634 | \& my $var : Selfish(@args); |
635 | .Ve |
636 | .PP |
637 | has the same effect as: |
638 | .PP |
639 | .Vb 1 |
640 | \& tie my $var, 'Tie::Selfish', @args; |
641 | .Ve |
642 | .PP |
643 | But when \f(CW"autotieref"\fR is used instead of \f(CW"autotie"\fR: |
644 | .PP |
645 | .Vb 2 |
646 | \& use Attribute::Handlers autotieref => { Selfish => Tie::Selfish }; |
647 | \& my $var : Selfish(@args); |
648 | .Ve |
649 | .PP |
650 | the effect is to pass the \f(CW\*(C`tie\*(C'\fR call an extra reference to the variable |
651 | being tied: |
652 | .PP |
653 | .Vb 1 |
654 | \& tie my $var, 'Tie::Selfish', \e$var, @args; |
655 | .Ve |
656 | .SH "EXAMPLES" |
657 | .IX Header "EXAMPLES" |
658 | If the class shown in \s-1SYNOPSIS\s0 were placed in the MyClass.pm |
659 | module, then the following code: |
660 | .PP |
661 | .Vb 2 |
662 | \& package main; |
663 | \& use MyClass; |
664 | .Ve |
665 | .PP |
666 | .Vb 1 |
667 | \& my MyClass $slr :Good :Bad(1**1\-1) :Omni(\-vorous); |
668 | .Ve |
669 | .PP |
670 | .Vb 2 |
671 | \& package SomeOtherClass; |
672 | \& use base MyClass; |
673 | .Ve |
674 | .PP |
675 | .Vb 1 |
676 | \& sub tent { 'acle' } |
677 | .Ve |
678 | .PP |
679 | .Vb 3 |
680 | \& sub fn :Ugly(sister) :Omni('po',tent()) {...} |
681 | \& my @arr :Good :Omni(s/cie/nt/); |
682 | \& my %hsh :Good(q/bye/) :Omni(q/bus/); |
683 | .Ve |
684 | .PP |
685 | would cause the following handlers to be invoked: |
686 | .PP |
687 | .Vb 1 |
688 | \& # my MyClass $slr :Good :Bad(1**1\-1) :Omni(\-vorous); |
689 | .Ve |
690 | .PP |
691 | .Vb 7 |
692 | \& MyClass::Good:ATTR(SCALAR)( 'MyClass', # class |
693 | \& 'LEXICAL', # no typeglob |
694 | \& \e$slr, # referent |
695 | \& 'Good', # attr name |
696 | \& undef # no attr data |
697 | \& 'CHECK', # compiler phase |
698 | \& ); |
699 | .Ve |
700 | .PP |
701 | .Vb 7 |
702 | \& MyClass::Bad:ATTR(SCALAR)( 'MyClass', # class |
703 | \& 'LEXICAL', # no typeglob |
704 | \& \e$slr, # referent |
705 | \& 'Bad', # attr name |
706 | \& 0 # eval'd attr data |
707 | \& 'CHECK', # compiler phase |
708 | \& ); |
709 | .Ve |
710 | .PP |
711 | .Vb 7 |
712 | \& MyClass::Omni:ATTR(SCALAR)( 'MyClass', # class |
713 | \& 'LEXICAL', # no typeglob |
714 | \& \e$slr, # referent |
715 | \& 'Omni', # attr name |
716 | \& '\-vorous' # eval'd attr data |
717 | \& 'CHECK', # compiler phase |
718 | \& ); |
719 | .Ve |
720 | .PP |
721 | .Vb 1 |
722 | \& # sub fn :Ugly(sister) :Omni('po',tent()) {...} |
723 | .Ve |
724 | .PP |
725 | .Vb 7 |
726 | \& MyClass::UGLY:ATTR(CODE)( 'SomeOtherClass', # class |
727 | \& \e*SomeOtherClass::fn, # typeglob |
728 | \& \e&SomeOtherClass::fn, # referent |
729 | \& 'Ugly', # attr name |
730 | \& 'sister' # eval'd attr data |
731 | \& 'CHECK', # compiler phase |
732 | \& ); |
733 | .Ve |
734 | .PP |
735 | .Vb 7 |
736 | \& MyClass::Omni:ATTR(CODE)( 'SomeOtherClass', # class |
737 | \& \e*SomeOtherClass::fn, # typeglob |
738 | \& \e&SomeOtherClass::fn, # referent |
739 | \& 'Omni', # attr name |
740 | \& ['po','acle'] # eval'd attr data |
741 | \& 'CHECK', # compiler phase |
742 | \& ); |
743 | .Ve |
744 | .PP |
745 | .Vb 1 |
746 | \& # my @arr :Good :Omni(s/cie/nt/); |
747 | .Ve |
748 | .PP |
749 | .Vb 7 |
750 | \& MyClass::Good:ATTR(ARRAY)( 'SomeOtherClass', # class |
751 | \& 'LEXICAL', # no typeglob |
752 | \& \e@arr, # referent |
753 | \& 'Good', # attr name |
754 | \& undef # no attr data |
755 | \& 'CHECK', # compiler phase |
756 | \& ); |
757 | .Ve |
758 | .PP |
759 | .Vb 7 |
760 | \& MyClass::Omni:ATTR(ARRAY)( 'SomeOtherClass', # class |
761 | \& 'LEXICAL', # no typeglob |
762 | \& \e@arr, # referent |
763 | \& 'Omni', # attr name |
764 | \& "" # eval'd attr data |
765 | \& 'CHECK', # compiler phase |
766 | \& ); |
767 | .Ve |
768 | .PP |
769 | .Vb 1 |
770 | \& # my %hsh :Good(q/bye) :Omni(q/bus/); |
771 | .Ve |
772 | .PP |
773 | .Vb 7 |
774 | \& MyClass::Good:ATTR(HASH)( 'SomeOtherClass', # class |
775 | \& 'LEXICAL', # no typeglob |
776 | \& \e%hsh, # referent |
777 | \& 'Good', # attr name |
778 | \& 'q/bye' # raw attr data |
779 | \& 'CHECK', # compiler phase |
780 | \& ); |
781 | .Ve |
782 | .PP |
783 | .Vb 7 |
784 | \& MyClass::Omni:ATTR(HASH)( 'SomeOtherClass', # class |
785 | \& 'LEXICAL', # no typeglob |
786 | \& \e%hsh, # referent |
787 | \& 'Omni', # attr name |
788 | \& 'bus' # eval'd attr data |
789 | \& 'CHECK', # compiler phase |
790 | \& ); |
791 | .Ve |
792 | .PP |
793 | Installing handlers into \s-1UNIVERSAL\s0, makes them...err..universal. |
794 | For example: |
795 | .PP |
796 | .Vb 2 |
797 | \& package Descriptions; |
798 | \& use Attribute::Handlers; |
799 | .Ve |
800 | .PP |
801 | .Vb 2 |
802 | \& my %name; |
803 | \& sub name { return $name{$_[2]}||*{$_[1]}{NAME} } |
804 | .Ve |
805 | .PP |
806 | .Vb 3 |
807 | \& sub UNIVERSAL::Name :ATTR { |
808 | \& $name{$_[2]} = $_[4]; |
809 | \& } |
810 | .Ve |
811 | .PP |
812 | .Vb 3 |
813 | \& sub UNIVERSAL::Purpose :ATTR { |
814 | \& print STDERR "Purpose of ", &name, " is $_[4]\en"; |
815 | \& } |
816 | .Ve |
817 | .PP |
818 | .Vb 3 |
819 | \& sub UNIVERSAL::Unit :ATTR { |
820 | \& print STDERR &name, " measured in $_[4]\en"; |
821 | \& } |
822 | .Ve |
823 | .PP |
824 | Let's you write: |
825 | .PP |
826 | .Vb 1 |
827 | \& use Descriptions; |
828 | .Ve |
829 | .PP |
830 | .Vb 3 |
831 | \& my $capacity : Name(capacity) |
832 | \& : Purpose(to store max storage capacity for files) |
833 | \& : Unit(Gb); |
834 | .Ve |
835 | .PP |
836 | .Vb 1 |
837 | \& package Other; |
838 | .Ve |
839 | .PP |
840 | .Vb 1 |
841 | \& sub foo : Purpose(to foo all data before barring it) { } |
842 | .Ve |
843 | .PP |
844 | .Vb 1 |
845 | \& # etc. |
846 | .Ve |
847 | .SH "UTILITY FUNCTIONS" |
848 | .IX Header "UTILITY FUNCTIONS" |
849 | This module offers a single utility function, \f(CW\*(C`findsym()\*(C'\fR. |
850 | .IP "findsym" 4 |
851 | .IX Item "findsym" |
852 | .Vb 1 |
853 | \& my $symbol = Attribute::Handlers::findsym($package, $referent); |
854 | .Ve |
855 | .Sp |
856 | The function looks in the symbol table of \f(CW$package\fR for the typeglob for |
857 | \&\f(CW$referent\fR, which is a reference to a variable or subroutine (\s-1SCALAR\s0, \s-1ARRAY\s0, |
858 | \&\s-1HASH\s0, or \s-1CODE\s0). If it finds the typeglob, it returns it. Otherwise, it returns |
859 | undef. Note that \f(CW\*(C`findsym\*(C'\fR memoizes the typeglobs it has previously |
860 | successfully found, so subsequent calls with the same arguments should be |
861 | must faster. |
862 | .SH "DIAGNOSTICS" |
863 | .IX Header "DIAGNOSTICS" |
864 | .ie n .IP """Bad attribute type: ATTR(%s)""" 4 |
865 | .el .IP "\f(CWBad attribute type: ATTR(%s)\fR" 4 |
866 | .IX Item "Bad attribute type: ATTR(%s)" |
867 | An attribute handler was specified with an \f(CW\*(C`:ATTR(\f(CIref_type\f(CW)\*(C'\fR, but the |
868 | type of referent it was defined to handle wasn't one of the five permitted: |
869 | \&\f(CW\*(C`SCALAR\*(C'\fR, \f(CW\*(C`ARRAY\*(C'\fR, \f(CW\*(C`HASH\*(C'\fR, \f(CW\*(C`CODE\*(C'\fR, or \f(CW\*(C`ANY\*(C'\fR. |
870 | .ie n .IP """Attribute handler %s doesn't handle %s attributes""" 4 |
871 | .el .IP "\f(CWAttribute handler %s doesn't handle %s attributes\fR" 4 |
872 | .IX Item "Attribute handler %s doesn't handle %s attributes" |
873 | A handler for attributes of the specified name \fIwas\fR defined, but not |
874 | for the specified type of declaration. Typically encountered whe trying |
875 | to apply a \f(CW\*(C`VAR\*(C'\fR attribute handler to a subroutine, or a \f(CW\*(C`SCALAR\*(C'\fR |
876 | attribute handler to some other type of variable. |
877 | .ie n .IP """Declaration of %s attribute in package %s may clash with future reserved word""" 4 |
878 | .el .IP "\f(CWDeclaration of %s attribute in package %s may clash with future reserved word\fR" 4 |
879 | .IX Item "Declaration of %s attribute in package %s may clash with future reserved word" |
880 | A handler for an attributes with an all-lowercase name was declared. An |
881 | attribute with an all-lowercase name might have a meaning to Perl |
882 | itself some day, even though most don't yet. Use a mixed-case attribute |
883 | name, instead. |
884 | .ie n .IP """Can't have two ATTR specifiers on one subroutine""" 4 |
885 | .el .IP "\f(CWCan't have two ATTR specifiers on one subroutine\fR" 4 |
886 | .IX Item "Can't have two ATTR specifiers on one subroutine" |
887 | You just can't, okay? |
888 | Instead, put all the specifications together with commas between them |
889 | in a single \f(CW\*(C`ATTR(\f(CIspecification\f(CW)\*(C'\fR. |
890 | .ie n .IP """Can't autotie a %s""" 4 |
891 | .el .IP "\f(CWCan't autotie a %s\fR" 4 |
892 | .IX Item "Can't autotie a %s" |
893 | You can only declare autoties for types \f(CW"SCALAR"\fR, \f(CW"ARRAY"\fR, and |
894 | \&\f(CW"HASH"\fR. They're the only things (apart from typeglobs \*(-- which are |
895 | not declarable) that Perl can tie. |
896 | .ie n .IP """Internal error: %s symbol went missing""" 4 |
897 | .el .IP "\f(CWInternal error: %s symbol went missing\fR" 4 |
898 | .IX Item "Internal error: %s symbol went missing" |
899 | Something is rotten in the state of the program. An attributed |
900 | subroutine ceased to exist between the point it was declared and the point |
901 | at which its attribute handler(s) would have been called. |
902 | .ie n .IP """Won't be able to apply END handler""" 4 |
903 | .el .IP "\f(CWWon't be able to apply END handler\fR" 4 |
904 | .IX Item "Won't be able to apply END handler" |
905 | You have defined an \s-1END\s0 handler for an attribute that is being applied |
906 | to a lexical variable. Since the variable may not be available during \s-1END\s0 |
907 | this won't happen. |
908 | .SH "AUTHOR" |
909 | .IX Header "AUTHOR" |
910 | Damian Conway (damian@conway.org). The maintainer of this module is now Rafael |
911 | Garcia-Suarez (rgarciasuarez@gmail.com). |
912 | .PP |
913 | Maintainer of the \s-1CPAN\s0 release is Steffen Mueller (smueller@cpan.org). |
914 | Contact him with technical difficulties with respect to the packaging of the |
915 | \&\s-1CPAN\s0 module. |
916 | .SH "BUGS" |
917 | .IX Header "BUGS" |
918 | There are undoubtedly serious bugs lurking somewhere in code this funky :\-) |
919 | Bug reports and other feedback are most welcome. |
920 | .SH "COPYRIGHT AND LICENSE" |
921 | .IX Header "COPYRIGHT AND LICENSE" |
922 | .Vb 3 |
923 | \& Copyright (c) 2001\-2009, Damian Conway. All Rights Reserved. |
924 | \& This module is free software. It may be used, redistributed |
925 | \& and/or modified under the same terms as Perl itself. |
926 | .Ve |