in reply to Re^6: Beyond Inside-Out (class)
in thread Beyond Inside-Out

You mean, runtime overriding methods for an object after the fact of its construction by manipulating the @ISA chain, while still expecting access to the original object data?

Uh, no, I don't mean that; not anything even close to that. How did you get this from the code I posted?

Submit this search to see some examples of one technique I'm familiar with that would cause the "problem". I suspect there are quite a few other techniques that would cause the same "problem", and I recall a recent thread where someone had the "SUPER:: doesn't work because caller() gives the wrong package" problem so I'm not the only person on the planet who has run into this.

It sounds like Anno has even seen this problem because s/he notes that the work-around of eval "package $pkg; sub $method { $code }" ... is burdensome.

I'm not making any claim to how common any such techniques are on CPAN (I don't search CPAN modules and compile statistics on which techniques are in use). If that is your criteria, then I should not have any qualms about doing things that would break Anno's approach because it isn't being used anywhere at all on CPAN. :)

I care because I consider some of these techniques to be good practices.

- tye        

Replies are listed 'Best First'.
Re^8: Beyond Inside-Out (did I get it?)
by shmem (Chancellor) on May 30, 2007 at 14:22 UTC
    Submit this search to see some examples of one technique I'm familiar with that would cause the "problem".

    Picking an example stub and populating it with code...

    package Foo::Bar; use vars qw( $VERSION ); sub method { my $self = shift; my $ego = __PACKAGE__.'::_implement::helper'; print "Foo::Bar::method: method = ", $ego->($self),"\n" } package Foo::Bar::_implement; use Alter qw(ego); sub helper { ego( shift)->{'method'}; } sub Foo::Bar::objectPackage { "Foo::Bar::Object"; } sub Foo::Bar::new { my $class = shift; warn "Foo::Bar::new(@_), class = $class\n"; my $thingy = bless \ my $ref, $class; ego ($thingy,{@_}); print "new thingy = $thingy\n"; $thingy; } sub Foo::Bar::Object::method { my $self = shift; print "Foo::Bar::Object::method: \$self = $self\n"; my $corona = ego( $self); print "Foo::Bar::Object::method: method = ",$corona->{'method'},"\ +n"; print "helper returns ",helper($self),"\n"; } 1;
    #!/usr/bin/perl my $foo = Foo::Bar->new(method => 'helper'); print "foo isa $foo\n"; $foo->method; my $meth = $foo->objectPackage.'::method'; $foo->$meth; __END__ Foo::Bar::new(method helper), class = Foo::Bar new thingy = Foo::Bar=SCALAR(0x8205ba4) foo isa Foo::Bar=SCALAR(0x8205ba4) Foo::Bar::method: method = helper Foo::Bar::Object::method: $self = Foo::Bar=SCALAR(0x8205ba4) Foo::Bar::Object::method: method = helper helper returns helper

    hmm... well (I might not have it populated like you would do :-). The Foo::Bar::new method is compiled into the package Foo::Bar::_implement, so a Foo::Bar object's class stash (or corona) will not be visible within methods compiled directly into the package Foo::Bar, and the only way is to crank the object through the "helper" sub above. But even if Foo::Bar is compiled into Foo::Bar::_implement, the corona can be forced into "the right package" (Foo::Bar) by swichting the package in the constructor:

    package Foo::Bar::_implement; sub Foo::Bar::new { my $class = shift; my $thingy = bless \ my $ref, $class; package Foo::Bar; ego ($thingy,{@_}); package Foo::Bar::_implement; $thingy; }

    which might also not be what you want. But somehow it must be decided what the "class" is supposed to be - is it the package or the subroutine qualifier? If it is the latter - quoting you from a previous note,

    The correct "class" is the package part of the subroutine name that was used to find the subroutine when the method was looked up (looking in symbol tables and following @ISA). Unfortunately, I have yet to see a way to get this information.
    how could that be different from what $class is in ($class = (caller(0))[3] ) =~ s/::[^:]+$// ?

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      how could that be different from what $class is in ($class = (caller(0)­)[3] ) =~ s/::[^:]+$­// ?

      Quoting myself:

      The correct thing to look up is not [...] nor the package part of the orignal name given to the subroutine (the two things that caller can give you).

      and

      *My::Modul­e::foo= \&Handy::G­etOrSet;

      So "Handy::GetOrSet" is the original name that uses a package name that has nothing to do with the class name of "My::Module".

      - tye        

        Well, Anno's technique doesn't claim to address that, let alone solve it.

        AFAIK caller looks up subroutine names via the coderef of the stack frame in question. While many entries in the symbol table may point to the same typeglob, the xgv_name field of that typeglob's coderef entry ever only holds one name, which is returned by caller.

        <update>

        Erm, no. Poking around with gdb (Perl_pp_caller, file pp_ctl.c)...

        ...the glob alias 'bar' is available via ccstack = (const PERL_CONTEXT *), now I have to find out how to resolve the right sv_any to get at the correct xgv_name field. Yes, but how? :-)

        </update>

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}