[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]

Re: On Pseudohashes



Sarathy wrote:

   > >   > One ought to be able to write:
   > >   > 
   > >   >         return $self->NEXT::m();

   > >And here's the implementation. Feedback most welcome.
   > 
   > I suspect this is going to be horribly expensive, because every NEXT::foo()
   > call will wipe out the method cache.

I evidently wasn't clear. I certainly wasn't proposing Class::Redispatch
as *the* implementation of NEXT, merely as a "proof-of-concept" for the 
usefulness of the facility. I particularly wanted to whet people's appetite
for easy hierarchical destructor calls. :-)

But I would fully expect that any real implementation of NEXT be coded
in the core, and use some form of caching of the current position in the
search tree, so that any redispatch could resume from that point.


   > There may be a better ways.  For example, for every package in the
   > inheritance tree that declares a CAN() method, that will be invoked with
   > the method being searched for along with its arguments.  CAN() can then
   > return a coderef/false value to determine if there exists a method to
   > be called in that package.  Of course, UNIVERSAL::can() would simply
   > call CAN() if it exists.  It would be possible to make this scheme fairly
   > efficient by keeping a bit on every stash where a CAN() method was seen
   > at compile time.

So then Class::Redispatch would insert localized CANs to make subsequent
redispatched lookups skip previously visited classes? That would
certainly work better than the current kludge. However, I can't see how
it would address the $obj->SUPER::m() vs $obj->B::m() ambiguity, which
$obj->NEXT::m() absolutely must resolve.

I still think t'were best done internally (as SUPER is).

Damian

PS: Here's a much better prototype. It still screws up the method
    caching, but it avoids evals, is stricter about were NEXT may be
    called (only from a method of the same name, or an AUTOLOAD), and
    only invalidates methods wrt calls via the current object. Feedback
    still welcome.

-----------cut-----------cut-----------cut-----------cut-----------cut----------

package NEXT;
use Carp;

sub AUTOLOAD
{
        my $self = shift;
        my $caller = (caller(1))[3]; 
        my ($class,$method) = $caller =~ m{(.*)::(.*)}g;
        my ($automethod) = $AUTOLOAD =~ m{.*::(.*)}g;
        croak "Can't call $AUTOLOAD from $caller"
                unless $method eq $automethod || $method eq 'AUTOLOAD';
        my $refclass = ref $self;
        my $refmethod = $refclass . '::' . $method;

        local %_seen = ( %_seen );
        $_seen{$self}{$caller} = \&$caller;
        $_seen{$self}{$refmethod} = \&$refmethod
                if $class ne $refclass and defined &$refmethod;

        undef *{$_} foreach (keys %{$_seen{$self}});
        $method = $self->can($method);
        *{$_} = $_seen{$self}{$_} foreach (keys %{$_seen{$self}});

        $self->$method(@_) if $method;
        return;
}

1;


[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index][Thread Index][Top&Search][Original]