[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

function lookups, just like method lookups! (was Re: [FWP] alienmethod calls)



On Apr 25, John Porter said:

>  sub Foo::goo { print ref($_[0])," Foo::goo\n"; }
>  sub Moo::goo { print ref($_[0])," Moo::goo\n"; }
>
>  my $o = bless {}, 'Foo';
>  $o->goo();		# prints "Moo Foo::goo"
>  $o->Moo::goo();	# prints "Moo Moo::goo"

That initial 'Moo' should be 'Foo'.  Calling a method on an object of a
different class doesn't change the object's reference type (as the typos
might suggest, or might not, or whatever).

I recently answered a question on DALnet #perl about @ISA -- the person
hadn't realized @ISA is only for method lookups, not function lookups:

  package Foo;
  @ISA = qw( Bar );
  $obj->method();  # might be Foo::method, might be Bar::method
  Foo->method();   # ditto

He had wanted to do:

  package Foo;
  @ISA = qw( Bar );
  method();  # method is in Bar

I told him to do one of:

  Foo->method();
  Bar->method();
  $self->method();  # it was in a sub, and he had an object in $self
  Bar::method();

Then I said he could do some AUTOLOAD tomfoolery.  The following is in the
UNIVERSAL namespace, but I could write a utility function to export this
AUTOLOAD() to a list of packages.

The basic gist is that it catches function calls from a package that
aren't defined, and traverses the ISA tree -- it's the method call lookup
for function calls.

  #!/usr/bin/perl

  package UNIVERSAL;
  $DEBUG = 1;
  sub AUTOLOAD {
    require Carp;
    no strict;
    local $\;
    my ($pkg,$func) = $AUTOLOAD =~ /(.*)::(.*)/;
    my ($file,$line) = (caller)[1,2];
    my @isa = @{ "${pkg}::ISA" };
    print STDERR "&$AUTOLOAD called at $file line $line\n" if $DEBUG;
    for (my $i = 0; $i < @isa; $i++) {
      $pkg = $isa[$i];
      splice @isa, $i+1, 0, @{ "${pkg}::ISA" };
      next unless defined &{ "${pkg}::$func" };
      print STDERR "&${pkg}::$func called\n" if $DEBUG;
      goto &{ "${pkg}::$func" };
    }
    Carp::croak("Undefined subroutine &$AUTOLOAD called");
  }

  package A;
  sub alpha { print 1, "@_" }
  sub beta { print 2 }
  sub gamma { print 3 }

  package B;
  @ISA = qw( A );
  sub bravo { print 5 }
  sub charlie { print 6 }
  alpha(),bravo(),gamma();

  package C;
  @ISA = qw( B );
  alpha(),bravo(),charlie();


Maybe God did not intend for this sort of mayhem. :)

-- 
MIDN 4/C PINYAN, NROTCURPI, US Naval Reserve             japhy@pobox.com
http://www.pobox.com/~japhy/                  http://pinyaj.stu.rpi.edu/
PerlMonth - An Online Perl Magazine            http://www.perlmonth.com/
The Perl Archive - Articles, Forums, etc.    http://www.perlarchive.com/


==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe