1Attribute::Handlers(3pm)Perl Programmers Reference GuideAttribute::Handlers(3pm)
2
3
4

NAME

6       Attribute::Handlers - Simpler definition of attribute handlers
7

VERSION

9       This document describes version 0.93 of Attribute::Handlers, released
10       July 20, 2011.
11

SYNOPSIS

13           package MyClass;
14           require 5.006;
15           use Attribute::Handlers;
16           no warnings 'redefine';
17
18
19           sub Good : ATTR(SCALAR) {
20               my ($package, $symbol, $referent, $attr, $data) = @_;
21
22               # Invoked for any scalar variable with a :Good attribute,
23               # provided the variable was declared in MyClass (or
24               # a derived class) or typed to MyClass.
25
26               # Do whatever to $referent here (executed in CHECK phase).
27               ...
28           }
29
30           sub Bad : ATTR(SCALAR) {
31               # Invoked for any scalar variable with a :Bad attribute,
32               # provided the variable was declared in MyClass (or
33               # a derived class) or typed to MyClass.
34               ...
35           }
36
37           sub Good : ATTR(ARRAY) {
38               # Invoked for any array variable with a :Good attribute,
39               # provided the variable was declared in MyClass (or
40               # a derived class) or typed to MyClass.
41               ...
42           }
43
44           sub Good : ATTR(HASH) {
45               # Invoked for any hash variable with a :Good attribute,
46               # provided the variable was declared in MyClass (or
47               # a derived class) or typed to MyClass.
48               ...
49           }
50
51           sub Ugly : ATTR(CODE) {
52               # Invoked for any subroutine declared in MyClass (or a
53               # derived class) with an :Ugly attribute.
54               ...
55           }
56
57           sub Omni : ATTR {
58               # Invoked for any scalar, array, hash, or subroutine
59               # with an :Omni attribute, provided the variable or
60               # subroutine was declared in MyClass (or a derived class)
61               # or the variable was typed to MyClass.
62               # Use ref($_[2]) to determine what kind of referent it was.
63               ...
64           }
65
66
67           use Attribute::Handlers autotie => { Cycle => Tie::Cycle };
68
69           my $next : Cycle(['A'..'Z']);
70

DESCRIPTION

72       This module, when inherited by a package, allows that package's class
73       to define attribute handler subroutines for specific attributes.
74       Variables and subroutines subsequently defined in that package, or in
75       packages derived from that package may be given attributes with the
76       same names as the attribute handler subroutines, which will then be
77       called in one of the compilation phases (i.e. in a "BEGIN", "CHECK",
78       "INIT", or "END" block). ("UNITCHECK" blocks don't correspond to a
79       global compilation phase, so they can't be specified here.)
80
81       To create a handler, define it as a subroutine with the same name as
82       the desired attribute, and declare the subroutine itself with the
83       attribute ":ATTR". For example:
84
85           package LoudDecl;
86           use Attribute::Handlers;
87
88           sub Loud :ATTR {
89               my ($package, $symbol, $referent, $attr, $data, $phase,
90                   $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           }
100
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:
104
105           package LoudDecl;
106
107           sub foo: Loud {...}
108
109       causes the above handler to be invoked, and passed:
110
111       [0] the name of the package into which it was declared;
112
113       [1] a reference to the symbol table entry (typeglob) containing the
114           subroutine;
115
116       [2] a reference to the subroutine;
117
118       [3] the name of the attribute;
119
120       [4] any data associated with that attribute;
121
122       [5] the name of the phase in which the handler is being invoked;
123
124       [6] the filename in which the handler is being invoked;
125
126       [7] the line number in this file.
127
128       Likewise, declaring any variables with the ":Loud" attribute within the
129       package:
130
131           package LoudDecl;
132
133           my $foo :Loud;
134           my @foo :Loud;
135           my %foo :Loud;
136
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).
139
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
145       to 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
158       argument ($_[4]) to a usable form before passing it to the handler (but
159       see "Non-interpretive attribute handlers").  If those efforts succeed,
160       the interpreted data is passed in an array reference; if they fail, the
161       raw 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/till, 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
178       as 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
190       variable is ascribed an attribute, the handler that is invoked is the
191       one 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
201       also 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 usable 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
271       to 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
345       Note that we now have to pass the cycling values as an array reference,
346       since the "autotie" mechanism passes "tie" a list of arguments as a
347       list (as in the Tie::Whatever example), not as an array reference (as
348       in the original Tie::Cycle example at the start of this section).
349
350       The argument after 'autotie' is a reference to a hash in which each key
351       is the name of an attribute to be created, and each value is the class
352       to which variables ascribed that attribute should be tied.
353
354       Note that there is no longer any need to import the Tie::Cycle module
355       -- Attribute::Handlers takes care of that automagically. You can even
356       pass arguments to the module's "import" subroutine, by appending them
357       to the class name. For example:
358
359           use Attribute::Handlers
360                autotie => { Dir => 'Tie::Dir qw(DIR_UNLINK)' };
361
362       If the attribute name is unqualified, the attribute is installed in the
363       current package. Otherwise it is installed in the qualifier's package:
364
365           package Here;
366
367           use Attribute::Handlers autotie => {
368                Other::Good => Tie::SecureHash, # tie attr installed in Other::
369                        Bad => Tie::Taxes,      # tie attr installed in Here::
370            UNIVERSAL::Ugly => Software::Patent # tie attr installed everywhere
371           };
372
373       Autoties are most commonly used in the module to which they actually
374       tie, and need to export their attributes to any module that calls them.
375       To facilitate this, Attribute::Handlers recognizes a special "pseudo-
376       class" -- "__CALLER__", which may be specified as the qualifier of an
377       attribute:
378
379           package Tie::Me::Kangaroo:Down::Sport;
380
381           use Attribute::Handlers autotie =>
382                { '__CALLER__::Roo' => __PACKAGE__ };
383
384       This causes Attribute::Handlers to define the "Roo" attribute in the
385       package that imports the Tie::Me::Kangaroo:Down::Sport module.
386
387       Note that it is important to quote the __CALLER__::Roo identifier
388       because a bug in perl 5.8 will refuse to parse it and cause an unknown
389       error.
390
391       Passing the tied object to "tie"
392
393       Occasionally it is important to pass a reference to the object being
394       tied to the TIESCALAR, TIEHASH, etc. that ties it.
395
396       The "autotie" mechanism supports this too. The following code:
397
398           use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };
399           my $var : Selfish(@args);
400
401       has the same effect as:
402
403           tie my $var, 'Tie::Selfish', @args;
404
405       But when "autotieref" is used instead of "autotie":
406
407           use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };
408           my $var : Selfish(@args);
409
410       the effect is to pass the "tie" call an extra reference to the variable
411       being tied:
412
413           tie my $var, 'Tie::Selfish', \$var, @args;
414

EXAMPLES

416       If the class shown in "SYNOPSIS" were placed in the MyClass.pm module,
417       then the following code:
418
419           package main;
420           use MyClass;
421
422           my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous);
423
424           package SomeOtherClass;
425           use base MyClass;
426
427           sub tent { 'acle' }
428
429           sub fn :Ugly(sister) :Omni('po',tent()) {...}
430           my @arr :Good :Omni(s/cie/nt/);
431           my %hsh :Good(q/bye/) :Omni(q/bus/);
432
433       would cause the following handlers to be invoked:
434
435           # my MyClass $slr :Good :Bad(1**1-1) :Omni(-vorous);
436
437           MyClass::Good:ATTR(SCALAR)( 'MyClass',          # class
438                                       'LEXICAL',          # no typeglob
439                                       \$slr,              # referent
440                                       'Good',             # attr name
441                                       undef               # no attr data
442                                       'CHECK',            # compiler phase
443                                     );
444
445           MyClass::Bad:ATTR(SCALAR)( 'MyClass',           # class
446                                      'LEXICAL',           # no typeglob
447                                      \$slr,               # referent
448                                      'Bad',               # attr name
449                                      0                    # eval'd attr data
450                                      'CHECK',             # compiler phase
451                                    );
452
453           MyClass::Omni:ATTR(SCALAR)( 'MyClass',          # class
454                                       'LEXICAL',          # no typeglob
455                                       \$slr,              # referent
456                                       'Omni',             # attr name
457                                       '-vorous'           # eval'd attr data
458                                       'CHECK',            # compiler phase
459                                     );
460
461
462           # sub fn :Ugly(sister) :Omni('po',tent()) {...}
463
464           MyClass::UGLY:ATTR(CODE)( 'SomeOtherClass',     # class
465                                     \*SomeOtherClass::fn, # typeglob
466                                     \&SomeOtherClass::fn, # referent
467                                     'Ugly',               # attr name
468                                     'sister'              # eval'd attr data
469                                     'CHECK',              # compiler phase
470                                   );
471
472           MyClass::Omni:ATTR(CODE)( 'SomeOtherClass',     # class
473                                     \*SomeOtherClass::fn, # typeglob
474                                     \&SomeOtherClass::fn, # referent
475                                     'Omni',               # attr name
476                                     ['po','acle']         # eval'd attr data
477                                     'CHECK',              # compiler phase
478                                   );
479
480
481           # my @arr :Good :Omni(s/cie/nt/);
482
483           MyClass::Good:ATTR(ARRAY)( 'SomeOtherClass',    # class
484                                      'LEXICAL',           # no typeglob
485                                      \@arr,               # referent
486                                      'Good',              # attr name
487                                      undef                # no attr data
488                                      'CHECK',             # compiler phase
489                                    );
490
491           MyClass::Omni:ATTR(ARRAY)( 'SomeOtherClass',    # class
492                                      'LEXICAL',           # no typeglob
493                                      \@arr,               # referent
494                                      'Omni',              # attr name
495                                      ""                   # eval'd attr data
496                                      'CHECK',             # compiler phase
497                                    );
498
499
500           # my %hsh :Good(q/bye) :Omni(q/bus/);
501
502           MyClass::Good:ATTR(HASH)( 'SomeOtherClass',     # class
503                                     'LEXICAL',            # no typeglob
504                                     \%hsh,                # referent
505                                     'Good',               # attr name
506                                     'q/bye'               # raw attr data
507                                     'CHECK',              # compiler phase
508                                   );
509
510           MyClass::Omni:ATTR(HASH)( 'SomeOtherClass',     # class
511                                     'LEXICAL',            # no typeglob
512                                     \%hsh,                # referent
513                                     'Omni',               # attr name
514                                     'bus'                 # eval'd attr data
515                                     'CHECK',              # compiler phase
516                                   );
517
518       Installing handlers into UNIVERSAL, makes them...err..universal.  For
519       example:
520
521           package Descriptions;
522           use Attribute::Handlers;
523
524           my %name;
525           sub name { return $name{$_[2]}||*{$_[1]}{NAME} }
526
527           sub UNIVERSAL::Name :ATTR {
528               $name{$_[2]} = $_[4];
529           }
530
531           sub UNIVERSAL::Purpose :ATTR {
532               print STDERR "Purpose of ", &name, " is $_[4]\n";
533           }
534
535           sub UNIVERSAL::Unit :ATTR {
536               print STDERR &name, " measured in $_[4]\n";
537           }
538
539       Let's you write:
540
541           use Descriptions;
542
543           my $capacity : Name(capacity)
544                        : Purpose(to store max storage capacity for files)
545                        : Unit(Gb);
546
547
548           package Other;
549
550           sub foo : Purpose(to foo all data before barring it) { }
551
552           # etc.
553

UTILITY FUNCTIONS

555       This module offers a single utility function, "findsym()".
556
557       findsym
558               my $symbol = Attribute::Handlers::findsym($package, $referent);
559
560           The function looks in the symbol table of $package for the typeglob
561           for $referent, which is a reference to a variable or subroutine
562           (SCALAR, ARRAY, HASH, or CODE). If it finds the typeglob, it
563           returns it. Otherwise, it returns undef. Note that "findsym"
564           memoizes the typeglobs it has previously successfully found, so
565           subsequent calls with the same arguments should be much faster.
566

DIAGNOSTICS

568       "Bad attribute type: ATTR(%s)"
569           An attribute handler was specified with an ":ATTR(ref_type)", but
570           the type of referent it was defined to handle wasn't one of the
571           five permitted: "SCALAR", "ARRAY", "HASH", "CODE", or "ANY".
572
573       "Attribute handler %s doesn't handle %s attributes"
574           A handler for attributes of the specified name was defined, but not
575           for the specified type of declaration. Typically encountered whe
576           trying to apply a "VAR" attribute handler to a subroutine, or a
577           "SCALAR" attribute handler to some other type of variable.
578
579       "Declaration of %s attribute in package %s may clash with future
580       reserved word"
581           A handler for an attributes with an all-lowercase name was
582           declared. An attribute with an all-lowercase name might have a
583           meaning to Perl itself some day, even though most don't yet. Use a
584           mixed-case attribute name, instead.
585
586       "Can't have two ATTR specifiers on one subroutine"
587           You just can't, okay?  Instead, put all the specifications together
588           with commas between them in a single "ATTR(specification)".
589
590       "Can't autotie a %s"
591           You can only declare autoties for types "SCALAR", "ARRAY", and
592           "HASH". They're the only things (apart from typeglobs -- which are
593           not declarable) that Perl can tie.
594
595       "Internal error: %s symbol went missing"
596           Something is rotten in the state of the program. An attributed
597           subroutine ceased to exist between the point it was declared and
598           the point at which its attribute handler(s) would have been called.
599
600       "Won't be able to apply END handler"
601           You have defined an END handler for an attribute that is being
602           applied to a lexical variable.  Since the variable may not be
603           available during END this won't happen.
604

AUTHOR

606       Damian Conway (damian@conway.org). The maintainer of this module is now
607       Rafael Garcia-Suarez (rgarciasuarez@gmail.com).
608
609       Maintainer of the CPAN release is Steffen Mueller (smueller@cpan.org).
610       Contact him with technical difficulties with respect to the packaging
611       of the CPAN module.
612

BUGS

614       There are undoubtedly serious bugs lurking somewhere in code this funky
615       :-) Bug reports and other feedback are most welcome.
616
618                Copyright (c) 2001-2009, Damian Conway. All Rights Reserved.
619              This module is free software. It may be used, redistributed
620                  and/or modified under the same terms as Perl itself.
621
622
623
624perl v5.16.3                      2013-03-04          Attribute::Handlers(3pm)
Impressum