package attributes;
-$VERSION = 0.01;
+our $VERSION = '0.04_01';
-#@EXPORT_OK = qw(get reftype);
-#@EXPORT = ();
+@EXPORT_OK = qw(get reftype);
+@EXPORT = ();
+%EXPORT_TAGS = (ALL => [@EXPORT, @EXPORT_OK]);
use strict;
#
# The extra trips through newATTRSUB in the interpreter wipe out any savings
# from avoiding the BEGIN block. Just do the bootstrap now.
-BEGIN { bootstrap }
+BEGIN { bootstrap attributes }
sub import {
- @_ > 2 && ref $_[2] or
- croak 'Usage: use '.__PACKAGE__.' $home_stash, $ref, @attrlist';
+ @_ > 2 && ref $_[2] or do {
+ require Exporter;
+ goto &Exporter::import;
+ };
my (undef,$home_stash,$svref,@attrs) = @_;
my $svtype = uc reftype($svref);
my $s = ((@pkgattrs == 1) ? '' : 's');
carp "$svtype package attribute$s " .
"may clash with future reserved word$s: " .
- join(' , ' , @pkgattrs);
+ join(' : ' , @pkgattrs);
}
}
}
croak "Invalid $svtype attribute" .
(( @badattrs == 1 ) ? '' : 's') .
": " .
- join(' , ', @badattrs);
+ join(' : ', @badattrs);
}
}
;
}
-#sub export {
-# require Exporter;
-# goto &Exporter::import;
-#}
-#
-#sub require_version { goto &UNIVERSAL::VERSION }
+sub require_version { goto &UNIVERSAL::VERSION }
1;
__END__
=head1 SYNOPSIS
sub foo : method ;
- my ($x,@y,%z) : Bent ;
+ my ($x,@y,%z) : Bent = 1;
my $s = sub : method { ... };
use attributes (); # optional, to get subroutine declarations
my @attrlist = attributes::get(\&foo);
+ use attributes 'get'; # import the attributes::get subroutine
+ my @attrlist = get \&foo;
+
=head1 DESCRIPTION
Subroutine declarations and definitions may optionally have attribute lists
associated with them. (Variable C<my> declarations also may, but see the
warning below.) Perl handles these declarations by passing some information
about the call site and the thing being declared along with the attribute
-list to this module. In particular, first example above is equivalent to
+list to this module. In particular, the first example above is equivalent to
the following:
use attributes __PACKAGE__, \&foo, 'method';
The second example in the synopsis does something equivalent to this:
- use attributes __PACKAGE__, \$x, 'Bent';
- use attributes __PACKAGE__, \@y, 'Bent';
- use attributes __PACKAGE__, \%z, 'Bent';
+ use attributes ();
+ my ($x,@y,%z);
+ attributes::->import(__PACKAGE__, \$x, 'Bent');
+ attributes::->import(__PACKAGE__, \@y, 'Bent');
+ attributes::->import(__PACKAGE__, \%z, 'Bent');
+ ($x,@y,%z) = 1;
-Yes, that's three invocations.
+Yes, that's a lot of expansion.
B<WARNING>: attribute declarations for variables are an I<experimental>
feature. The semantics of such declarations could change or be removed
package-specific attributes are allowed by an extension mechanism.
(See L<"Package-specific Attribute Handling"> below.)
-The setting of attributes happens at compile time. An attempt to set
+The setting of subroutine attributes happens at compile time.
+Variable attributes in C<our> declarations are also applied at compile time.
+However, C<my> variables get their attributes applied at run-time.
+This means that you have to I<reach> the run-time component of the C<my>
+before those attributes will get applied. For example:
+
+ my $x : Bent = 42 if 0;
+
+will neither assign 42 to $x I<nor> will it apply the C<Bent> attribute
+to the variable.
+
+An attempt to set
an unrecognized attribute is a fatal error. (The error is trappable, but
it still stops the compilation within that C<eval>.) Setting an attribute
with a name that's all lowercase letters that's not a built-in attribute
as described there. It also means that a subroutine so marked
will not trigger the "Ambiguous call resolved as CORE::%s" warning.
+=item lvalue
+
+Indicates that the referenced subroutine is a valid lvalue and can
+be assigned to. The subroutine must return a modifiable value such
+as a scalar variable, as described in L<perlsub>.
+
=back
There are no built-in attributes for anything other than subroutines.
+=for hackers
+What about C<unique>?
+
=head2 Available Subroutines
The following subroutines are available for general use once this module
to raise a fatal exception. If it can find an appropriate package name
for a class method lookup, it will include the results from a
C<FETCH_I<type>_ATTRIBUTES> call in its return list, as described in
-L"Package-specific Attribute Handling"> below.
+L<"Package-specific Attribute Handling"> below.
Otherwise, only L<built-in attributes|"Built-in Attributes"> will be returned.
=item reftype
variable. It returns the built-in type of the referenced variable,
ignoring any package into which it might have been blessed.
This can be useful for determining the I<type> value which forms part of
-the method names described in L"Package-specific Attribute Handling"> below.
+the method names described in L<"Package-specific Attribute Handling"> below.
=back
-Note that these routines are I<not> exported. This is primarily because
-the C<use> mechanism which would normally import them is already in use
-by Perl itself to implement the C<sub : attributes> syntax.
+Note that these routines are I<not> exported by default.
=head2 Package-specific Attribute Handling
=head2 Syntax of Attribute Lists
An attribute list is a sequence of attribute specifications, separated by
-whitespace, commas, or both. Each attribute specification is a simple
+whitespace or a colon (with optional whitespace).
+Each attribute specification is a simple
name, optionally followed by a parenthesised parameter list.
If such a parameter list is present, it is scanned past as for the rules
for the C<q()> operator. (See L<perlop/"Quote and Quote-like Operators">.)
Some examples of syntactically valid attribute lists:
- switch(10,foo(7,3)) , , expensive
- Ugly('\(") , Bad
+ switch(10,foo(7,3)) : expensive
+ Ugly('\(") :Bad
_5x5
locked method
Ugly('(') # ()-string not balanced
5x5 # "5x5" not a valid identifier
Y2::north # "Y2::north" not a simple identifier
- foo + bar # "+" neither a comma nor whitespace
+ foo + bar # "+" neither a colon nor whitespace
+
+=head1 EXPORTS
+
+=head2 Default exports
+
+None.
+
+=head2 Available exports
+
+The routines C<get> and C<reftype> are exportable.
+
+=head2 Export tags defined
+
+The C<:ALL> tag will get all of the above exports.
=head1 EXAMPLES
Effect:
- use attributes Canine => \$spot, "Watchful";
+ use attributes ();
+ attributes::->import(Canine => \$spot, "Watchful");
=item 2.
Effect:
- use attributes Felis => \$cat, "Nervous";
+ use attributes ();
+ attributes::->import(Felis => \$cat, "Nervous");
=item 3.