Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery

Class::Std : How does MODIFY_HASH_ATTRIBUTES work?

by esharris (Monk)
on Oct 13, 2005 at 19:18 UTC ( #499997=perlquestion: print w/replies, xml ) Need Help??
esharris has asked for the wisdom of the Perl Monks concerning the following question:

In Class::Std, there is a MODIFY_HASH_ATTRIBUTES subroutine. The Class::Std perldocs show how to append :ATTR( ...) to hash declarations. How does Perl know to apply MODIFY_HASH_ATTRIBUTES to any hash declarations with attributes? Is MODIFY_HASH_ATTRIBUTES a special name to Perl? I want to understand the mechanism that supports the automatic generation of subroutines.
  • Comment on Class::Std : How does MODIFY_HASH_ATTRIBUTES work?

Replies are listed 'Best First'.
Re: Class::Std : How does MODIFY_HASH_ATTRIBUTES work?
by xdg (Monsignor) on Oct 13, 2005 at 21:24 UTC

    It's part of the attributes mechanism. It's automatically called to handle the attributes of an appropriate type:


    This method is called with two fixed arguments, followed by the list of attributes from the relevant declaration. The two fixed arguments are the relevant package name and a reference to the declared subroutine or variable. The expected return value is a list of attributes which were not recognized by this handler. Note that this allows for a derived class to delegate a call to its base class, and then only examine the attributes which the base class didn't already handle for it.

    The call to this method is currently made *during* the processing of the declaration. In particular, this means that a subroutine reference will probably be for an undefined subroutine, even if this declaration is actually part of the definition.

    You might also want to browse the source of Attribute::Handlers for examples of how they get used.

    Updated: expanded answer...

    attributes came into being around Perl 5.6. When Perl sees an attribute (see perlsub for the syntax), the attribute gets expanded into a call to the attributes module.

    my %name : ATTR; # becomes use attributes (); my %name; attributes::->import(__PACKAGE__, \%name, 'ATTR');

    attributes in turn, looks for a MODIFY_*_ATTRIBUTES in the current package or the @ISA array and calls it to handle the attribute. If that function returns any attributes, those are "unhandled" attributes and the import croaks with an error.

    MODIFY_*_ATTRIBUTES receives the package name, a reference to the item attributed, and a list of attributes attached. E.g. in Class::Std:

    sub MODIFY_HASH_ATTRIBUTES { my ($package, $referent, @attrs) = @_; ...

    The rest of that routine checks for an "ATTR" attribute, extracts any information passed along with it, like defaults, and installs the accessors as "usual". For example:

    if ($getter = _extract_get($config)) { no strict 'refs'; *{$package.'::get_'.$getter} = sub { return $referent->{ID($_[0])}; } }

    The only "magic" here is the way that Perl automatically expands the ":ATTR" into a call to the attributes module. After that, it's just normal function calls between modules.

    CAVEAT: this all happens at compile time -- so it's like a BEGIN block and certain things aren't yet set up. This is why in MODIFY_CODE_ATTRIBUTES, the name and reference of the method are just pushed onto a data structure, and the actual handling of the attribute occurs later in the CHECK block, after the method has been compiled.

    (This is why anything build with Class::Std won't work with mod_perl, which has no CHECK phase. You can see an approach which will work in my own experimental Object::LocalVars, which requires the module using it to make an explicit function call to give_methods which gets run after its compilation when the module is first loaded in what is effectively a BEGIN phase at that point.)


    Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://499997]
Approved by Corion
Front-paged by kwaping
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2017-03-25 12:12 GMT
Find Nodes?
    Voting Booth?
    Should Pluto Get Its Planethood Back?

    Results (311 votes). Check out past polls.