develooper Front page | perl.perl6.announce.rfc | Postings from October 2000

RFC 337 (v2) Common attribute system to allow user-defined, extensible attributes

Perl6 RFC Librarian
October 1, 2000 17:51
RFC 337 (v2) Common attribute system to allow user-defined, extensible attributes
Message ID:
This and other RFCs are available on the web at

=head1 TITLE

Common attribute system to allow user-defined, extensible attributes

=head1 VERSION

  Maintainer: Nathan Wiger <>
  Date: 28 Sep 2000
  Last Modified: 1 Oct 2000
  Mailing List:
  Number: 337
  Version: 2
  Status: Frozen


Camel-3 and others have proposed a syntax for declaring variables like

   my type $var :attr1 :attr2 = $val;

However, nobody has firmly nailed down what C<:attr1> and C<:attr2> are
supposed to do. This takes a shot at it, since this could simplify the
implementation of B<RFC 188>, B<RFC 336>, B<RFC 163>, and others.

Currently, the C<attributes> module can be used to set and retrieve
these attributes. However, the current C<MODIFY_ATTRIBUTES> and
C<FETCH_ATTRIBUTES> subs are not really fine-grained enough to give
really good control. It would be nice to be able to call specialized,
delegateable and inheritable subs to handle attributes. Furthermore,
these attribute handlers should be able to alter Perl's internals
somewhat, perhaps through the C<use optimize> pragma.


Attributes should be able to access some type of core hooks so that they
can be defined by the user and extended arbitrarily. For example, in
pseudocode, a user should be able to say something like this:

   package Dog;

   attr fluffy {
        causes numeric contexts to fail;
        results in stringification appending "--and fluffy";

Then, if a user does the following:

   my Dog $spot :fluffy = "happy";
   print "$spot";                   # "happy--and fluffy";
   $spot++;                         # fails 

So, the declaration of C<:fluffy> would trigger the execution of a
specific attribute handler, which could make the necessary changes to
the variable.

This would allow B<RFC 188>, which proposes new C<private> and C<public>
keywords, to instead be implemented as attributes. This is perhaps more
appropriate since these do not alter lexical scope (unlike C<my> and
C<our>), but rather change properties of the variables themselves:

   package __ALL__;     # some type of builtin global declaration
   attr private {
        attachable to hashes and hash keys only;
        marks entire hash as non-autovivifying;
        marks specific entry as private to the package;
        allows duplication of keys in different packages;
        leaves any other entries public;

   attr public {
        attachable to hashes and hash keys only;
        marks specific entry as accessible by all packages;
        would take the entry out of the package symbol table;

In your code, then, you could use the C<:private> and C<:public>
attributes to modify your variables:

   sub new {
         my ($class, %self) = @_;
         bless \%self :private, $class;
         $self{seed} = rand;             # dies, can't autovivify
         $self{seed} :private = rand;    # okay
         $self{seed} = rand;             # now okay

In addition, perhaps we have a BigInt class that we need to be able to

   package BigInt;

   attr 128bit {
        attachable to any variable;
        causes exception if 128 bits not supported;
        results in huge memory preallocation;
        does other neato stuff too; 

Again, in your code:

   my BigInt $x :128bit;

This would invoke the attribute to modify the variable's properties
internally. By having some type of attribute-specific declaration
method, the attribute system could be modifiable at will, allowing for
native access to variable manipulation without the need to compile a new
version of Perl.

This would allow those who want to to warp Perl OO into Java or Python
or C++ without these features having to be either widely used or
embedded in core. A base class could simply define attribute handlers
which other classes could then inherit from. Attributes would be
inherited just like subs.

Attributes are not necessarily tied to C<my> or C<our> declarations; see
B<RFC 279> for details.


The easiest way I see is to change the C<attributes> pragma into a
pre-declaration pragma instead, something like:

   package Foo;
   use attributes fluffy => 'DEFAULT',
                  size => \&SIZE_ATTR,
                  UNKNOWN => \&ATTR_HANDLER;

So, the declaration of C<:fluffy> on an instance of C<Foo> would just
result in it being stored as text retrievable via C<attributes::get> or
some other means. On declaration of C<:size('big')>, though, the
C<SIZE_ATTR(\$var, 'big')> sub from the class would be called. That is,
a reference to the variable being altered would be the first arg, and
the attribute arguments would be passed in by value.

Any unknown attributes would be thrown to the C<ATTR_HANDLER> sub, which
would take the name of the attribute as the first arg, and then the
other args would look like any other handler. For example:

   my Foo $bar :baz('likely');  # Foo->ATTR_HANDLER('baz', \$bar,
                                #                   'likely')

The name of the unknown attribute is the first arg so it can easily be
shifted off.

In both scenarios, the attributes should always be retrievable at a
later time. However, the declaration of an attribute should also be able
to trigger the execution of a specific sub that can make changes to
internals (perhaps through the C<use optimize> pragma), to the data for
that object, or something else.

Note that you could even add a C<use strict 'attrs'> pragma that
dictated you could only use predeclared attributes. This could help
catch mistyping of important ones:

   package Parallel;
   use attributes slippery => \&FALL_OFF;

   package main;
   use strict 'attrs';
   my Parallel $bar :slipery;    # raise exception

Here, we've caught a typo that might result in badness later.


This alters the current meaning of attribute handling. From the man page
on C<>:

   WARNING: the mechanisms described here are still experimental.
   Do not rely on the current implementation.  In particular, there
   is no provision for applying package attributes to 'cloned' copies
   of subroutines used as closures.  (See the Making References entry
   in the perlref manpage for information on closures.)  Package-
   specific attribute handling may change incompatibly in a future

Like Michael Schwern said in RFC 241, "You pays your money and you takes
your chances." ;-)


RFC 279: my() syntax extensions and attribute declarations

RFC 218: C<my Dog $spot> is just an assertion

RFC 303: Keep C<use less>, but make it work.

RFC 270: Replace XS with the C<Inline> module as the standard way to extend Perl.

RFC 188: Objects : Private keys and methods

RFC 163: Objects: Autoaccessors for object data structures

RFC 336: use strict 'objects': a new pragma for using Java-like objects in Perl Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About