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.78 of Attribute::Handlers, released
10       October 5, 2002.
11

SYNOPSIS

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

DESCRIPTION

70       This module, when inherited by a package, allows that package's class
71       to define attribute handler subroutines for specific attributes. Vari‐
72       ables and subroutines subsequently defined in that package, or in pack‐
73       ages derived from that package may be given attributes with the same
74       names as the attribute handler subroutines, which will then be called
75       in one of the compilation phases (i.e. in a "BEGIN", "CHECK", "INIT",
76       or "END" block).
77
78       To create a handler, define it as a subroutine with the same name as
79       the desired attribute, and declare the subroutine itself with the
80       attribute ":ATTR". For example:
81
82               package LoudDecl;
83               use Attribute::Handlers;
84
85               sub Loud :ATTR {
86                       my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
87                       print STDERR
88                               ref($referent), " ",
89                               *{$symbol}{NAME}, " ",
90                               "($referent) ", "was just declared ",
91                               "and ascribed the ${attr} attribute ",
92                               "with data ($data)\n",
93                               "in phase $phase\n";
94               }
95
96       This creates a handler for the attribute ":Loud" in the class LoudDecl.
97       Thereafter, any subroutine declared with a ":Loud" attribute in the
98       class LoudDecl:
99
100               package LoudDecl;
101
102               sub foo: Loud {...}
103
104       causes the above handler to be invoked, and passed:
105
106       [0] the name of the package into which it was declared;
107
108       [1] a reference to the symbol table entry (typeglob) containing the
109           subroutine;
110
111       [2] a reference to the subroutine;
112
113       [3] the name of the attribute;
114
115       [4] any data associated with that attribute;
116
117       [5] the name of the phase in which the handler is being invoked.
118
119       Likewise, declaring any variables with the ":Loud" attribute within the
120       package:
121
122               package LoudDecl;
123
124               my $foo :Loud;
125               my @foo :Loud;
126               my %foo :Loud;
127
128       will cause the handler to be called with a similar argument list
129       (except, of course, that $_[2] will be a reference to the variable).
130
131       The package name argument will typically be the name of the class into
132       which the subroutine was declared, but it may also be the name of a
133       derived class (since handlers are inherited).
134
135       If a lexical variable is given an attribute, there is no symbol table
136       to which it belongs, so the symbol table argument ($_[1]) is set to the
137       string 'LEXICAL' in that case. Likewise, ascribing an attribute to an
138       anonymous subroutine results in a symbol table argument of 'ANON'.
139
140       The data argument passes in the value (if any) associated with the
141       attribute. For example, if &foo had been declared:
142
143               sub foo :Loud("turn it up to 11, man!") {...}
144
145       then the string "turn it up to 11, man!" would be passed as the last
146       argument.
147
148       Attribute::Handlers makes strenuous efforts to convert the data argu‐
149       ment ($_[4]) to a useable form before passing it to the handler (but
150       see "Non-interpretive attribute handlers").  For example, all of these:
151
152               sub foo :Loud(till=>ears=>are=>bleeding) {...}
153               sub foo :Loud(['till','ears','are','bleeding']) {...}
154               sub foo :Loud(qw/till ears are bleeding/) {...}
155               sub foo :Loud(qw/my, ears, are, bleeding/) {...}
156               sub foo :Loud(till,ears,are,bleeding) {...}
157
158       causes it to pass "['till','ears','are','bleeding']" as the handler's
159       data argument. However, if the data can't be parsed as valid Perl, then
160       it is passed as an uninterpreted string. For example:
161
162               sub foo :Loud(my,ears,are,bleeding) {...}
163               sub foo :Loud(qw/my ears are bleeding) {...}
164
165       cause the strings 'my,ears,are,bleeding' and 'qw/my ears are bleeding'
166       respectively to be passed as the data argument.
167
168       If the attribute has only a single associated scalar data value, that
169       value is passed as a scalar. If multiple values are associated, they
170       are passed as an array reference. If no value is associated with the
171       attribute, "undef" is passed.
172
173       Typed lexicals
174
175       Regardless of the package in which it is declared, if a lexical vari‐
176       able is ascribed an attribute, the handler that is invoked is the one
177       belonging to the package to which it is typed. For example, the follow‐
178       ing declarations:
179
180               package OtherClass;
181
182               my LoudDecl $loudobj : Loud;
183               my LoudDecl @loudobjs : Loud;
184               my LoudDecl %loudobjex : Loud;
185
186       causes the LoudDecl::Loud handler to be invoked (even if OtherClass
187       also defines a handler for ":Loud" attributes).
188
189       Type-specific attribute handlers
190
191       If an attribute handler is declared and the ":ATTR" specifier is given
192       the name of a built-in type ("SCALAR", "ARRAY", "HASH", or "CODE"), the
193       handler is only applied to declarations of that type. For example, the
194       following definition:
195
196               package LoudDecl;
197
198               sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" }
199
200       creates an attribute handler that applies only to scalars:
201
202               package Painful;
203               use base LoudDecl;
204
205               my $metal : RealLoud;           # invokes &LoudDecl::RealLoud
206               my @metal : RealLoud;           # error: unknown attribute
207               my %metal : RealLoud;           # error: unknown attribute
208               sub metal : RealLoud {...}      # error: unknown attribute
209
210       You can, of course, declare separate handlers for these types as well
211       (but you'll need to specify "no warnings 'redefine'" to do it quietly):
212
213               package LoudDecl;
214               use Attribute::Handlers;
215               no warnings 'redefine';
216
217               sub RealLoud :ATTR(SCALAR) { print "Yeeeeow!" }
218               sub RealLoud :ATTR(ARRAY) { print "Urrrrrrrrrr!" }
219               sub RealLoud :ATTR(HASH) { print "Arrrrrgggghhhhhh!" }
220               sub RealLoud :ATTR(CODE) { croak "Real loud sub torpedoed" }
221
222       You can also explicitly indicate that a single handler is meant to be
223       used for all types of referents like so:
224
225               package LoudDecl;
226               use Attribute::Handlers;
227
228               sub SeriousLoud :ATTR(ANY) { warn "Hearing loss imminent" }
229
230       (I.e. "ATTR(ANY)" is a synonym for ":ATTR").
231
232       Non-interpretive attribute handlers
233
234       Occasionally the strenuous efforts Attribute::Handlers makes to convert
235       the data argument ($_[4]) to a useable form before passing it to the
236       handler get in the way.
237
238       You can turn off that eagerness-to-help by declaring an attribute han‐
239       dler with the keyword "RAWDATA". For example:
240
241               sub Raw          : ATTR(RAWDATA) {...}
242               sub Nekkid       : ATTR(SCALAR,RAWDATA) {...}
243               sub Au::Naturale : ATTR(RAWDATA,ANY) {...}
244
245       Then the handler makes absolutely no attempt to interpret the data it
246       receives and simply passes it as a string:
247
248               my $power : Raw(1..100);        # handlers receives "1..100"
249
250       Phase-specific attribute handlers
251
252       By default, attribute handlers are called at the end of the compilation
253       phase (in a "CHECK" block). This seems to be optimal in most cases
254       because most things that can be defined are defined by that point but
255       nothing has been executed.
256
257       However, it is possible to set up attribute handlers that are called at
258       other points in the program's compilation or execution, by explicitly
259       stating the phase (or phases) in which you wish the attribute handler
260       to be called. For example:
261
262               sub Early    :ATTR(SCALAR,BEGIN) {...}
263               sub Normal   :ATTR(SCALAR,CHECK) {...}
264               sub Late     :ATTR(SCALAR,INIT) {...}
265               sub Final    :ATTR(SCALAR,END) {...}
266               sub Bookends :ATTR(SCALAR,BEGIN,END) {...}
267
268       As the last example indicates, a handler may be set up to be (re)called
269       in two or more phases. The phase name is passed as the handler's final
270       argument.
271
272       Note that attribute handlers that are scheduled for the "BEGIN" phase
273       are handled as soon as the attribute is detected (i.e. before any sub‐
274       sequently defined "BEGIN" blocks are executed).
275
276       Attributes as "tie" interfaces
277
278       Attributes make an excellent and intuitive interface through which to
279       tie variables. For example:
280
281               use Attribute::Handlers;
282               use Tie::Cycle;
283
284               sub UNIVERSAL::Cycle : ATTR(SCALAR) {
285                       my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
286                       $data = [ $data ] unless ref $data eq 'ARRAY';
287                       tie $$referent, 'Tie::Cycle', $data;
288               }
289
290               # and thereafter...
291
292               package main;
293
294               my $next : Cycle('A'..'Z');     # $next is now a tied variable
295
296               while (<>) {
297                       print $next;
298               }
299
300       Note that, because the "Cycle" attribute receives its arguments in the
301       $data variable, if the attribute is given a list of arguments, $data
302       will consist of a single array reference; otherwise, it will consist of
303       the single argument directly. Since Tie::Cycle requires its cycling
304       values to be passed as an array reference, this means that we need to
305       wrap non-array-reference arguments in an array constructor:
306
307               $data = [ $data ] unless ref $data eq 'ARRAY';
308
309       Typically, however, things are the other way around: the tieable class
310       expects its arguments as a flattened list, so the attribute looks like:
311
312               sub UNIVERSAL::Cycle : ATTR(SCALAR) {
313                       my ($package, $symbol, $referent, $attr, $data, $phase) = @_;
314                       my @data = ref $data eq 'ARRAY' ? @$data : $data;
315                       tie $$referent, 'Tie::Whatever', @data;
316               }
317
318       This software pattern is so widely applicable that Attribute::Handlers
319       provides a way to automate it: specifying 'autotie' in the "use
320       Attribute::Handlers" statement. So, the cycling example, could also be
321       written:
322
323               use Attribute::Handlers autotie => { Cycle => 'Tie::Cycle' };
324
325               # and thereafter...
326
327               package main;
328
329               my $next : Cycle(['A'..'Z']);     # $next is now a tied variable
330
331               while (<>) {
332                       print $next;
333
334       Note that we now have to pass the cycling values as an array reference,
335       since the "autotie" mechanism passes "tie" a list of arguments as a
336       list (as in the Tie::Whatever example), not as an array reference (as
337       in the original Tie::Cycle example at the start of this section).
338
339       The argument after 'autotie' is a reference to a hash in which each key
340       is the name of an attribute to be created, and each value is the class
341       to which variables ascribed that attribute should be tied.
342
343       Note that there is no longer any need to import the Tie::Cycle module
344       -- Attribute::Handlers takes care of that automagically. You can even
345       pass arguments to the module's "import" subroutine, by appending them
346       to the class name. For example:
347
348               use Attribute::Handlers
349                       autotie => { Dir => 'Tie::Dir qw(DIR_UNLINK)' };
350
351       If the attribute name is unqualified, the attribute is installed in the
352       current package. Otherwise it is installed in the qualifier's package:
353
354               package Here;
355
356               use Attribute::Handlers autotie => {
357                       Other::Good => Tie::SecureHash, # tie attr installed in Other::
358                               Bad => Tie::Taxes,      # tie attr installed in Here::
359                   UNIVERSAL::Ugly => Software::Patent # tie attr installed everywhere
360               };
361
362       Autoties are most commonly used in the module to which they actually
363       tie, and need to export their attributes to any module that calls them.
364       To facilitate this, Attribute::Handlers recognizes a special
365       "pseudo-class" -- "__CALLER__", which may be specified as the qualifier
366       of an attribute:
367
368               package Tie::Me::Kangaroo:Down::Sport;
369
370               use Attribute::Handlers autotie => { '__CALLER__::Roo' => __PACKAGE__ };
371
372       This causes Attribute::Handlers to define the "Roo" attribute in the
373       package that imports the Tie::Me::Kangaroo:Down::Sport module.
374
375       Note that it is important to quote the __CALLER__::Roo identifier
376       because a bug in perl 5.8 will refuse to parse it and cause an unknown
377       error.
378
379       Passing the tied object to "tie"
380
381       Occasionally it is important to pass a reference to the object being
382       tied to the TIESCALAR, TIEHASH, etc. that ties it.
383
384       The "autotie" mechanism supports this too. The following code:
385
386               use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };
387               my $var : Selfish(@args);
388
389       has the same effect as:
390
391               tie my $var, 'Tie::Selfish', @args;
392
393       But when "autotieref" is used instead of "autotie":
394
395               use Attribute::Handlers autotieref => { Selfish => Tie::Selfish };
396               my $var : Selfish(@args);
397
398       the effect is to pass the "tie" call an extra reference to the variable
399       being tied:
400
401               tie my $var, 'Tie::Selfish', \$var, @args;
402

EXAMPLES

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

DIAGNOSTICS

539       "Bad attribute type: ATTR(%s)"
540           An attribute handler was specified with an ":ATTR(ref_type)", but
541           the type of referent it was defined to handle wasn't one of the
542           five permitted: "SCALAR", "ARRAY", "HASH", "CODE", or "ANY".
543
544       "Attribute handler %s doesn't handle %s attributes"
545           A handler for attributes of the specified name was defined, but not
546           for the specified type of declaration. Typically encountered whe
547           trying to apply a "VAR" attribute handler to a subroutine, or a
548           "SCALAR" attribute handler to some other type of variable.
549
550       "Declaration of %s attribute in package %s may clash with future
551       reserved word"
552           A handler for an attributes with an all-lowercase name was
553           declared. An attribute with an all-lowercase name might have a
554           meaning to Perl itself some day, even though most don't yet. Use a
555           mixed-case attribute name, instead.
556
557       "Can't have two ATTR specifiers on one subroutine"
558           You just can't, okay?  Instead, put all the specifications together
559           with commas between them in a single "ATTR(specification)".
560
561       "Can't autotie a %s"
562           You can only declare autoties for types "SCALAR", "ARRAY", and
563           "HASH". They're the only things (apart from typeglobs -- which are
564           not declarable) that Perl can tie.
565
566       "Internal error: %s symbol went missing"
567           Something is rotten in the state of the program. An attributed sub‐
568           routine ceased to exist between the point it was declared and the
569           point at which its attribute handler(s) would have been called.
570
571       "Won't be able to apply END handler"
572           You have defined an END handler for an attribute that is being
573           applied to a lexical variable.  Since the variable may not be
574           available during END this won't happen.
575

AUTHOR

577       Damian Conway (damian@conway.org)
578

BUGS

580       There are undoubtedly serious bugs lurking somewhere in code this funky
581       :-) Bug reports and other feedback are most welcome.
582
584                Copyright (c) 2001, Damian Conway. All Rights Reserved.
585              This module is free software. It may be used, redistributed
586                  and/or modified under the same terms as Perl itself.
587
588
589
590perl v5.8.8                       2001-09-21          Attribute::Handlers(3pm)
Impressum