Description :
This module, when inherited by a package, allows that package\'s class to define attribute handler subroutines for specific attributes. Variables and subroutines subsequently defined in that package, or in packages derived from that package may be given attributes with the same names as the attribute handler subroutines, which will then be called in one of the compilation phases (i.e. in a \'BEGIN\', \'CHECK\', \'INIT\', or \'END\' block). (\'UNITCHECK\' blocks don\'t correspond to a global compilation phase, so they can\'t be specified here.)
To create a handler, define it as a subroutine with the same name as the desired attribute, and declare the subroutine itself with the attribute \':ATTR\'. For example:
package LoudDecl; use Attribute::Handlers;
sub Loud :ATTR { my ($package, $symbol, $referent, $attr, $data, $phase, $filename, $linenum) = AATT_; print STDERR ref($referent), \" \", *{$symbol}{NAME}, \" \", \"($referent) \", \"was just declared \", \"and ascribed the ${attr} attribute \", \"with data ($data)\ \", \"in phase $phase\ \", \"in file $filename at line $linenum\ \"; }
This creates a handler for the attribute \':Loud\' in the class LoudDecl. Thereafter, any subroutine declared with a \':Loud\' attribute in the class LoudDecl:
package LoudDecl;
sub foo: Loud {...}
causes the above handler to be invoked, and passed:
* [0]
the name of the package into which it was declared;
* [1]
a reference to the symbol table entry (typeglob) containing the subroutine;
* [2]
a reference to the subroutine;
* [3]
the name of the attribute;
* [4]
any data associated with that attribute;
* [5]
the name of the phase in which the handler is being invoked;
* [6]
the filename in which the handler is being invoked;
* [7]
the line number in this file.
Likewise, declaring any variables with the \':Loud\' attribute within the package:
package LoudDecl;
my $foo :Loud; my AATTfoo :Loud; my %foo :Loud;
will cause the handler to be called with a similar argument list (except, of course, that \'$_[2]\' will be a reference to the variable).
The package name argument will typically be the name of the class into which the subroutine was declared, but it may also be the name of a derived class (since handlers are inherited).
If a lexical variable is given an attribute, there is no symbol table to which it belongs, so the symbol table argument (\'$_[1]\') is set to the string \'\'LEXICAL\'\' in that case. Likewise, ascribing an attribute to an anonymous subroutine results in a symbol table argument of \'\'ANON\'\'.
The data argument passes in the value (if any) associated with the attribute. For example, if \'&foo\' had been declared:
sub foo :Loud(\"turn it up to 11, man!\") {...}
then a reference to an array containing the string \'\"turn it up to 11, man!\"\' would be passed as the last argument.
Attribute::Handlers makes strenuous efforts to convert the data argument (\'$_[4]\') to a usable form before passing it to the handler (but see \"Non-interpretive attribute handlers\"). If those efforts succeed, the interpreted data is passed in an array reference; if they fail, the raw data is passed as a string. For example, all of these:
sub foo :Loud(till=>ears=>are=>bleeding) {...} sub foo :Loud(qw/till ears are bleeding/) {...} sub foo :Loud(qw/till, ears, are, bleeding/) {...} sub foo :Loud(till,ears,are,bleeding) {...}
causes it to pass \'[\'till\',\'ears\',\'are\',\'bleeding\']\' as the handler\'s data argument. While:
sub foo :Loud([\'till\',\'ears\',\'are\',\'bleeding\']) {...}
causes it to pass \'[ [\'till\',\'ears\',\'are\',\'bleeding\'] ]\'; the array reference specified in the data being passed inside the standard array reference indicating successful interpretation.
However, if the data can\'t be parsed as valid Perl, then it is passed as an uninterpreted string. For example:
sub foo :Loud(my,ears,are,bleeding) {...} sub foo :Loud(qw/my ears are bleeding) {...}
cause the strings \'\'my,ears,are,bleeding\'\' and \'\'qw/my ears are bleeding\'\' respectively to be passed as the data argument.
If no value is associated with the attribute, \'undef\' is passed.
|