mshiltonj has asked for the wisdom of the Perl Monks concerning the following question:

Oh wise perl masters, I am humbly seeking guidance.

I just recently discovered subroutine attributes in perl, because I'm starting to read about Catalyst. I kind of get them, but really I don't. :-/

I've read many documents on attributes, but something still isn't clicking for me. The Attribute::Deprecated module is a good basic example of how use to attributes based on the Attribute::Handlers module. I can use attributes that way and get it.

But, to get a deeper understanding (and because this is how Catalyst uses attributes), I've been trying to use the attributes pragma directly, but the documentation isn't answering a question I still have. The Catalyst code on this isn't a good example for me because it looks to be so highly optimized.

My question is illustrated by the code I have below, right on the "magic happens here" line.

How do I create the magic?

#!/usr/bin/perl -w use strict; use attributes; sub FETCH_CODE_ATTRIBUTES { return qw(Big Damn Test); } sub MODIFY_CODE_ATTRIBUTES { my ( $class, $code, @attrs ) = @_; if ( $class ne 'main' ) { if (my $code = $class->SUPER::can('MODIFY_CODE_ATTRIBUTES')) { @attrs = $code->( $class, $code, @attrs ); } } my @unknown; foreach my $attr (@attrs) { if ( 1 ) { # yeah, I'm supposed to handle this attribute # "There is no spoon." # Magic Happens Here .. ??? } else { push @unknown, $attr; } } return @unknown; } sub foo : Big Damn Test { warn "SPOOON!"; } foo();
Thanks so much for any help on this.
-- mshiltonj

Replies are listed 'Best First'.
Re: How do you use/create subroutine attributes?
by xdg (Monsignor) on Mar 17, 2006 at 20:08 UTC

    The last time I saw this type of question asked, I wrote Re: Class::Std : How does MODIFY_HASH_ATTRIBUTES work?. See if that helps clarify things -- it does also briefly cover it in the context of CODE attributes as well.

    -xdg

    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.

Re: How do you use/create subroutine attributes?
by stvn (Monsignor) on Mar 17, 2006 at 20:00 UTC

    Well, it all depends on what kind of magic you want to happen.

    I am pretty sure that MODIFY_CODE_ATTRIBUTES will run in the BEGIN phase of the perl compiler. And the $code passed to you is usually a stub, and not the true subroutine that you will eventually have (however it's ref address will stay the same, so you can use that). What Catalyst does is to store the code-ref address along with the list of attributes it had for it, then when Catalyst is initialized (sometime during runtime presumably) it matches code-refs to attributes (using attribute::get() which calls FETCH_CODE_ATTRIBUTES) and does magic then. Attribute::Handlers does similar stuff, but it uses the INIT phase of the perl compiler to do it's dirty work.

    In general subroutine attributes are an unwieldy beast with a really bad interface. They are especially tricky when it comes to CODE references. But then again, this is my experience, and your mileage may vary.

    -stvn

      Supposedly, Attribute::Handlers can act at any compilation stage, though the default is CHECK, as that's a point at which most things are compiled and in place. The big limitation is that the name in the symbol table for a subroutine isn't set at the time attributes are first processed -- only the package name and the code reference (that later gets stored in the symbol table) are available.

      Technically, the MODIFY_*_ATTRIBUTES from Attribute::Handlers runs immediately during compilation (like a BEGIN block) -- but by default, Attribute::Handlers just stores everything it can about the call at that point. Later, during CHECK, it calls the appropriate handlers on the previously stored information, which, among other things, allows looking up the name of the coderef in the symbol table to find the name of a subroutine.

      -xdg

      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.