Professional Perl | 22
[next] |
Professional Perl
Attribute Lists
Attributes are a largely experimental feature, still under development, and only present from Perl version 5.6 onwards, so accordingly we have left them to the end of the chapter. The use of attributes in production code is not recommended, but being aware of them is not a bad idea, since they will ultimately mature into an official part of the language.
In brief, attributes are pieces of information associated with either variables or subroutines that can be set to modify their behavior in specific ways. The primary users of attributes are subroutines. Perl recognizes and understands three special attributes, lvalue, locked, and method, which alter the way in which the Perl interpreter executes subroutines. It is more than likely other special attributes will appear as Perl evolves. We have already seen lvalue in this chapter, and cover locked and method in brief below.
Currently, we cannot define our own attributes on either variables or subroutines, only those defined and understood by Perl. However, an experimental package attribute mechanism, which associates user-defined attributes with packages, is under development. All variables and subroutines that reside in the package automatically have the package attributes associated with them.
Attributes can be placed on both subroutines and lexical variables. The basic form of a variable attribute list is one or more variables declared with 'my' followed by a semicolon and the attribute list. However, there are no variable attributes currently understood by Perl.
Defining Attributes on Subroutines
The basic form of a subroutine attribute list is a standard subroutine definition (or declaration), followed by a colon and the attributes to be defined. Attributes are separated by white space, and optionally a colon. They are then followed by the body of the subroutine or (in the case of a declaration) a semicolon:
sub mysubroutine : attr1 : attr2 { # standard subroutine
... body of subroutine ...
}
sub mysubroutine : attr1 attr2; # subroutine declaration
my $subref = sub : attr1 : attr2 { # anonymous subroutine
... body of subroutine ...
}
sub mysubroutine (\@$$;$) : attr; # declaration with prototype
sub mysubroutine attr (parameters); # attribute with parameters
At the time of writing, the attributes lvalue, locked, and method are the only attributes that can be set. None of these use a parameter list as shown in the last example, but the syntax accepts the possibility in anticipation of future applications.
Accessing Attributes
Attribute definitions are actually handled by the attributes pragmatic module, which implements the modified syntax for variables and subroutines that allows them to be defined. The attributes module also supplies subroutines to access these attributes, which we can use by importing them from the attributes module:
use attributes qw(get reftype); # import 'get' and 'reftype' subroutines
The get subroutine takes a variable, or subroutine reference, and returns a list of attributes defined on that reference. If there are none, then the list is empty. For example:
sub mysubroutine : locked method {
...
}
my @attrlist = get \&mysubroutine; # contains ('locked', 'method')
The reftype subroutine also takes a reference to a variable or subroutine. It returns the underlying reference type; HASH for a hash variable, CODE for a subroutine reference, and so on. Blessed references return the underlying data type, which makes reftype a potentially useful subroutine as a replacement for ref, even if we are not using attributes.
Special Attributes
Perl currently defines three attributes with special meanings - locked, method, and lvalue. Of all the aspects of attributes discussed so far, these are the most immediately useful.
The lvalue attribute allows subroutines to return assignable values, rather like the substr function does when used on a variable, as we discussed earlier in the chapter.
The locked attribute is useful in threaded programming, when more than one thread of execution can call the same subroutine simultaneously. In many cases, such subroutines need to complete one call before the next can proceed, such as writing complex information to a file or the screen, or handing a database transaction. In order to stop simultaneous calls from treading on each other's toes, we can lock the subroutine so that only one thread can execute it at any time:
sub oneatatimeplease : locked {
# only one thread can execute this subroutine at a time.
}
The method attribute is used in object classes to indicate that a locked subroutine should lock on a per-object basis. It modifies the effect of the locked attribute to apply itself to the first argument of the subroutine. In an object method this is the blessed reference representing the object. As a result, the method block only calls if the object being passed is already busy in that method; other objects of the same class proceed unhindered:
sub objectmethodlock : locked : method {
my $self = shift;
# only one thread can execute this method on the same object
# but different threads can execute it on different objects
}
Whether or not it is used with locked, method also prevents Perl from confusing it with a built-in function of the same name. We can therefore create a method called print and be sure that it will only be used when an object-oriented call to print is made. Only if the subroutine is called as an object method will Perl call it instead of the built-in function.
We cover the locked and method attributes in a little more detail when we discuss threaded programming in Perl in chapter 22.
Contents |
[next] |
Created: May 02, 2001
Revised: May 02, 2001