Due too some of the discussion on Class::InsideOut I have discovered that I am missing some of the subtleties of perl's lexical pads, and their interaction with package-specific attributes.

Basically, lexical pads don't seem to be as localised as I thought they would be - and attribute subroutines seem to be being called in an odd context.

(Background: I am largely unfamiliar with the perl internals. I've skimmed perlguts and related docs but can't find anything obvious that answers my questions. However, I've worked on compilers for other languages and am familiar with the basic concepts.)

My naive concept of perl's lexical pads that there would be one associated with each lexical scope something like this.

# new pad here for the file's scope { # new pad here for the block's scope } sub foo { # new pad here for the subroutine's scope } ... etc ...

and from my reading of attributes in perl 5.8 doing.

my %foo : Bar = (answer => 42);

should be the same as

use attributes (); my %foo; attributes::->import(__PACKAGE__, \%z, 'Bent'); %foo = (answer => 42);

However, some experiments with PadWalker show my understanding is in error:

use strict; use warnings; package AttrTest; use Data::Dumper; use PadWalker qw(peek_my); sub MODIFY_HASH_ATTRIBUTES { my ($package, $reference, @attributes) = @_; $package->dump_lex("setting @attributes in $package for $reference +"); return; }; sub dump_lex { my ($class, $when) = @_; print "when $when top-level pad is\n"; my $level=0; while (eval {peek_my(++$level)} && !$@) {}; my $hash = peek_my($level-1); while (my ($name, $value) = each %$hash) { my $dumped = Data::Dumper->new([\$value],[$name])->Indent(0)-> +Dump; print "\t$value -> $dumped\n"; }; print "\n"; }; INIT { AttrTest->dump_lex('init') }; { package Foo; use base qw(AttrTest); my %foo : Attr = (one => 1); }; { package Bar; use base qw(AttrTest); use attributes (); my %bar; attributes::->import(__PACKAGE__, \%bar, 'Attr'); } AttrTest->dump_lex('runtime');

Under perl 5.6 this produces

when setting Attr in Foo for HASH(0x8187bec) top-level pad is + SCALAR(0x8186018) -> $%foo = \\'%foo'; + + when init top-level pad is + HASH(0x818bf68) -> $%bar = \{}; + HASH(0x8187bec) -> $%foo = \{}; + + when setting Attr in Bar for HASH(0x818bf68) top-level pad is + HASH(0x818bf68) -> $%bar = \{}; + + when runtime top-level pad is

Under perl 5.8 this produces

when init top-level pad is HASH(0x22dda8) -> $%bar = \{}; HASH(0x3cff4) -> $%foo = \{}; when setting Attr in Foo for HASH(0x3cff4) top-level pad is when setting Attr in Bar for HASH(0x22dda8) top-level pad is HASH(0x22dda8) -> $%bar = \{}; when runtime top-level pad is

Both examples used the same version of PadWalker (v0.08). I am also aware of the change in 5.8 that means attributes declared with my are now applied at runtime.

This output confuses me for a couple of reasons:

I realise that package-specific attributes are still considered experimental - so I'm not particularly worried about the different behaviour - but I would like to understand what's going on :-)

Can any perl internals guru's explain to this poor confused soul?


In reply to Lexical pad / attribute confusion by adrianh

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.