Book Home Programming PerlSearch this book

6.5. Subroutine Attributes

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 Chapter 31, "Pragmatic Modules" for internal details. There are three standard attributes for subroutines: locked, method, and lvalue.

6.5.1. The locked and method Attributes

# 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, "Threads", 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.

6.5.2. The lvalue Attribute

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.



Library Navigation Links

Copyright © 2001 O'Reilly & Associates. All rights reserved.