A subroutine declaration or definition may have a list
of attributes associated with it. If such an attribute list is
present, it is broken up at whitespace or colon boundaries and treated
as though a use attributes
had been seen. See the
use attributes
pragma in Glossary for internal details. There
are three standard attributes for subroutines:
locked
, method
, and
lvalue
.
# Only one thread is allowed into this function. sub afunc : locked { … } # Only one thread is allowed into this function on a given object. sub afunc : locked method { … }
Setting the locked
attribute is meaningful
only when the subroutine or method is intended to be called by
multiple threads simultaneously. When set on a nonmethod subroutine,
Perl ensures that a lock is acquired on the subroutine itself before
that subroutine is entered. When set on a method subroutine (that
is, one also marked with the method
attribute),
Perl ensures that any invocation of it implicitly locks its first
argument (the object) before execution.
Semantics of this lock are the same as using the
lock
operator on the subroutine as the first
statement in that routine. See Chapter
17, for more on locking.
The method
attribute can be used by
itself:
sub afunc : method { … }
Currently this has only the effect of marking the subroutine
so as not to trigger the "Ambiguous call resolved as
CORE::%s
" warning. (We may make it mean more
someday.)
The attribute system is user-extensible, letting you
create your own attribute names. These new attributes must be valid
as simple identifier names (without any punctuation other than the
"_
" character). They may have a parameter list
appended, which is currently only checked for whether its
parentheses nest properly.
Here are examples of valid syntax (even though the attributes are unknown):
sub fnord (&\%) : switch(10,foo(7,3)) : expensive; sub plugh () : Ugly('(") :Bad; sub xyzzy : _5x5 { … }
Here are examples of invalid syntax:
sub fnord : switch(10,foo(); # ()-string not balanced sub snoid : Ugly('('), # ()-string not balanced sub xyzzy : 5x5; # "5x5" not a valid identifier sub plugh : Y2::north; # "Y2::north" not a simple identifier sub snurt : foo + bar; # "+" not a colon or space
The attribute list is passed as a list of constant strings to the code that associates them with the subroutine. Exactly how this works (or doesn't) is highly experimental. Check attributes (3) for current details on attribute lists and their manipulation.
It is possible to return a modifiable scalar value from a subroutine, but only if you declare the subroutine to return an lvalue:
my $val; sub canmod : lvalue { $val; } sub nomod { $val; } canmod() = 5; # Assigns to $val. nomod() = 5; # ERROR
If you're passing parameters to an lvalued subroutine, you'll usually want parentheses to disambiguate what's being assigned:
canmod $x = 5; # assigns 5 to $x first! canmod 42 = 5; # can't change a constant; compile-time error canmod($x) = 5; # this is ok canmod(42) = 5; # and so is this
If you want to be sneaky, you can get around this in the
particular case of a subroutine that takes one argument. Declaring
the function with a prototype of ($)
causes the
function to be parsed with the precedence of a named unary operator.
Since named unaries have higher precedence than assignment, you no
longer need the parentheses. (Whether this is desirable or not is
left up to the style police.)
You don't have to be sneaky in the particular case of a
subroutine that allows zero arguments (that is, with a
()
prototype). You can without ambiguity say
this:
canmod = 5;
That works because no valid term begins with
=
. Similarly, lvalued method calls can omit the
parentheses when you don't pass any arguments:
$obj->canmod = 5;
We promise not to break those two constructs in future versions of Perl. They're handy when you want to wrap object attributes in method calls (so that they can be inherited like method calls but accessed like variables).
The scalar or list context of both the lvalue subroutine and the righthand side of an assignment to that subroutine is determined as if the subroutine call were replaced by a scalar. For example, consider:
data(2,3) = get_data(3,4);
Both subroutines here are called in scalar context, while in:
(data(2,3)) = get_data(3,4);
and in:
(data(2),data(3)) = get_data(3,4);
all the subroutines are called in list context.
The current implementation does not allow arrays and hashes to be returned from lvalue subroutines directly. You can always return a reference instead.