Phoenix.pm: Attribute::Handlers and BEGIN blocks -- question(s)

Shay Harding sharding at ccbill.com
Mon Dec 24 01:21:54 CST 2001


This got so long I'm going to post up top so you don't have to scroll...

After some investigation it seems both of you are kind of correct. The

$test : Test;

was getting parsed before the BEGIN blocks, as it is checked at compile time 
since this is valid Perl syntax and is something I did not even know existed.

The ':' is used to set attributes for subroutines as 'locked' or 'method'. 
>From perldelta, perl 5.6:

---------------------------------------------------------
New syntax for declaring subroutine attributes
 
Formerly, if you wanted to mark a subroutine as being a method call or as 
requiring an automatic lock() when it is entered, you had to declare that 
with a `use attrs' pragma in the body of the subroutine.  That can now be 
accomplished with declaration syntax, like this:
 
           sub mymethod : locked method ;
           ...
           sub mymethod : locked method {
               ...
           }
 
           sub othermethod :locked :method ;
           ...
           sub othermethod :locked :method {
               ...
           }
 
(Note how only the first `:' is mandatory, and whitespace surrounding 
the `:' is optional.)
 
AutoSplit.pm and SelfLoader.pm have been updated to keep the attributes with 
the stubs they provide.  See the attributes manpage.
--------------------------------------------------------------

>From the attrs.pm pod:

-----------------------------------------------------
=head1 DESCRIPTION
 
NOTE: Use of this pragma is deprecated.  Use the syntax
 
    sub foo : locked method { }
 
to declare attributes instead.  See also L<attributes>.
 
This pragma lets you set and get attributes for subroutines.
Setting attributes takes place at compile time; trying to set
invalid attribute names causes a compile-time error. Calling
C<attrs::get> on a subroutine reference or name returns its list
of attribute names. Notice that C<attrs::get> is not exported.
------------------------------------------------------

So it seems these attributes were orignally entered in for use with threads. 
Learn something new everyday :)

Attribute::Handlers seems to take this a step further and can be applied to 
subroutined, scalars, hashes, arrays, etc.


Shay


On Sunday 23 December 2001 20:15, you wrote:
> At 03:46 PM 12/22/01 -0700, you wrote:
> >Hello all,
> >
> >Have a question for anyone that might be familiar with Attribute::Handlers
> >module. Even if you're not familiar maybe you can provide insight into why
> >the following is happening...
> >
> >Ok, first BEGIN blocks should be evaluated before the rest of the script,
> >FIFO order. So the following:
> >
> >
> >#!/usr/bin/perl
> >
> >print "Top of script\n";
> >
> >BEGIN{
> >     print "BEGIN 1\n";
> >}
> >
> >print "Middle\n";
> >
> >BEGIN{
> >     print "BEGIN 2\n";
> >}
> >
> >
> >will print:
> >
> >BEGIN 1
> >BEGIN 2
> >Top of script
> >Middle
> >
> >
> >Now take the following code:
> >
> >#!/usr/bin/perl
> >
> >   my $test : Test;  #set an attribute for variable
> >
> >   print "Top\n";
> >
> >    BEGIN{
> >        print "In BEGIN 1\n";
> >        use Attribute::Handlers;
> >        sub Test($;) : ATTR(SCALAR, BEGIN) {
> >            print "In profiled sub\n";
> >        }
> >    }
> >
> >   print "Middle\n";
> >
> >   BEGIN{
> >       print "In BEGIN 2\n";
> >   }
> >
> >
> >This gives the following error:
> >
> >Invalid SCALAR attribute: Test at t.pl line 3
> >BEGIN failed--compilation aborted at t.pl line 3.
> >
> >
> >which I really don't understand as it seems it is parsing '$test : Test;'
> >before the BEGIN blocks? I try to assign $test right after the attribute
> >setting and display it within the BEGIN blocks but under -w gives the
> >following (which I would expect):
> >
> >Use of uninitialized value in concatenation (.) at t.pl line 9.
> >
> >because $test should not exist within the BEGIN block meaning it hasn't
> > yet been looked at by the compiler.
> >
> >Why then do I get the 'Invalid SCALAR arttribute' error? The order of
> >processing in the above code is:
> >
> >Attribute::Handlers::import
> >BEGIN 1
> >BEGIN 2
> >script
> >
> >Which means the atribute handler Test should be parsed before the
> > assignment of $test...
> >
> >I know I can fix it by moving the assignment but I'm just curoius as to
> > why it is happening.
>
> I'm not familiar with Attribute::Handlers, so take this with a grain of
> salt...
>
> I checked Programming Perl 3rd Ed., and thus spake the camel (on page 465):
>
>    BEGIN blocks are handed off to the interpreter to be RUN as as(sic) soon
> as they are
>    parsed, which effectively runs them in FIFO order (first in, first
> out).  (Emphasis mine)
>
> I would guess that Attribute::Handlers is playing some magic with Perl's
> syntax, and if that syntax is used before the "use Attribute::Handlers"
> (which is treated like a BEGIN), the perl compiler will barf on the
> unrecognized syntax. So, compile wise, it should be this:
>
> script
> BEGIN 1
> Attribute::Handlers::import
> script
> BEGIN 2
>
> I'm in over my head, so I could be wrong.  Does anyone else want to confirm
> or deny this?



More information about the Phoenix-pm mailing list