adrianh has asked for the wisdom of the Perl Monks concerning the following question:
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:
- Why can INIT see %foo and %bar? They are not in the scope of the INIT subroutine and, since they are in their own blocks, they should not be visible from the file-scoped pad (the last call to dump_lex doesn't show them)?
- Why can't the implicit call to MODIFY_HASH_ATTRIBUTES in Foo see %foo in perl 5.8? The attribute routine is being called at runtime so the hash should have been declared and be in the pad?
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?
|
---|
Replies are listed 'Best First'. | |
---|---|
Re: Lexical pad / attribute confusion
by djantzen (Priest) on Dec 21, 2002 at 23:48 UTC | |
by adrianh (Chancellor) on Dec 21, 2002 at 23:58 UTC | |
by shotgunefx (Parson) on Dec 22, 2002 at 00:00 UTC | |
by adrianh (Chancellor) on Dec 22, 2002 at 00:08 UTC | |
by shotgunefx (Parson) on Dec 22, 2002 at 01:04 UTC | |
| |
Re: Lexical pad / attribute confusion
by Aristotle (Chancellor) on Dec 22, 2002 at 00:57 UTC | |
by djantzen (Priest) on Dec 22, 2002 at 01:37 UTC | |
by diotalevi (Canon) on Dec 22, 2002 at 02:37 UTC | |
by adrianh (Chancellor) on Dec 22, 2002 at 01:58 UTC | |
by djantzen (Priest) on Dec 22, 2002 at 02:05 UTC | |
Re: Lexical pad / attribute confusion
by adrianh (Chancellor) on Dec 22, 2002 at 14:20 UTC | |
by diotalevi (Canon) on Dec 23, 2002 at 12:11 UTC | |
by adrianh (Chancellor) on Dec 23, 2002 at 22:12 UTC |