Special Attributes - Page 26
July 27, 2001
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.
Package Attributes
Package attributes are an experimental feature implemented in the
attributes module. We will do no more than take a
brief look at what they are supposed to do here, because the
mechanism and syntax of how they are defined and used is likely
to change at some point.
The idea of package attributes is that we can implement our own
attributes that work on a package-wide basis. To implement them,
we write specially named subroutines within the package that will
be called by the get subroutine mentioned above.
Each different type may (or may not) have a distinct set of
attributes associated with it, so a scalar variable has different
attributes from an array, but all scalar variables in the package
share the same set of attributes. This is very similar in concept
to the way that tied variables work.
Attributes are stored and returned according to the package
implementation. A given attribute data type is implemented by
writing FETCH_X_ATTRIBUTES and
MODIFY_X_ATTRIBUTES subroutines, where
X is the data type — either
SCALAR, ARRAY, or HASH.
The package may implement the details of storage and retrieval
any way it likes, just as with tied variables. To retrieve
attributes on subroutines, we define
FETCH_CODE_ATTRIBUTES, and to allow them to be set
as well, we define MODIFY_CODE_ATTRIBUTES.
FETCH subroutines are called by get whenever we use
it on a reference of the correct type in the same package. They
are passed a single argument, which is a reference to the entity
being queried. They return a list of the attributes defined for
that entity.
MODIFY subroutines are called during the import
stage of compilation. They take a package name and a reference as
their first two arguments, followed by a list of attributes to
define. They return a list of unrecognized attributes, which may
be empty.
The current design also allows for packages that inherit
attributes from a parent package by calling
SUPER::FETCH_X_ATTRIBUTES and
SUPER::MODIFY_X_ATTRIBUTES. The intent is that a
child FETCH or MODIFY subroutine should
first call its parent, and then deal with any attributes
returned. In the case of FETCH, it adds its own
attributes to the list and returns it. In the case of
MODIFY, it deals with the list of unrecognized
attributes passed back from the parent.
Summary
In this chapter we saw how to declare and call subroutines.
Specifically we looked at anonymous subroutines, subroutine
references, and the use strict subs pragma. Next we
looked at predeclaring subroutines, and learned how to override
built-in functions. After this, we learned about the internal
stack, which Perl uses to hold details of subroutines, and saw an
example of a recursive subroutine.
Several issues concerning the passing of parameters were covered, including:
- Passing lists and hashes.
- Converting scalar subroutines into list processors
- Passing @_ directly into subroutines
- Named parameters
Prototypes were discussed in-depth, and the topics covered included the following:
- Defining the number of parameters
- Prototyping code references
- Subroutines as scalar operators
- Optional parameters
- Disabling prototypes
Following this, we looked at how to return values from
subroutines, and saw how to return the undefined value, and
determine and respond to the calling context. Finally, we covered
attribute lists, and looked at defining attributes on
subroutines, accessing attributes, special attributes, and
package attributes.
Attribute Lists - Page 25
Professional Perl Programming
|