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

The correct thing to look up is not what package the code was compiled into, nor the package part of the orignal name given to the subroutine (the two things that caller can give you). 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. That is why you'd need to provide a way to override how the class name is determined.

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? Could you name me some Modules which do that devilry so I can immediately scratch them from my list of useful modules, if only for lack of understanding and never wishing to have to debug them? Or is it just that I can't follow?

If you mean altering the inheritance chain to make the object mutate and show a distinct behaviour depending on the current context, that works fine with Anno's approach.

--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}

Replies are listed 'Best First'.
Re^7: Beyond Inside-Out (no)
by tye (Sage) on May 29, 2007 at 21:35 UTC
    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        

      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