jkeenan1 has asked for the wisdom of the Perl Monks concerning the following question:

The following question concerning NEXT.pm was posed on comp.lang.perl.modules on Jan 13 2005 by J Krugman. I was able to confirm the problem but unable to diagnose the illness. SuperSearch suggests the problem has not previouly been discussed in the monastery. Since the posting hasn't attracted any other responses, I figured it would be a good idea to consult the monks.

J Krugman: Before I go off an file a bug report, I want to make sure that I got things right. In the SYNOPSIS section for Damian Conway's NEXT module's POD, there's the following extended example:

use NEXT; package A; sub A::method { print "$_[0]: A method\n"; $_[0]->NEXT::method() } sub A::DESTROY { print "$_[0]: A dtor\n"; $_[0]->NEXT::DESTROY() } package B; use base qw( A ); sub B::AUTOLOAD { print "$_[0]: B AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub B::DESTROY { print "$_[0]: B dtor\n"; $_[0]->NEXT::DESTROY() } package C; sub C::method { print "$_[0]: C method\n"; $_[0]->NEXT::method() } sub C::AUTOLOAD { print "$_[0]: C AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub C::DESTROY { print "$_[0]: C dtor\n"; $_[0]->NEXT::DESTROY() } package D; use base qw( B C ); sub D::method { print "$_[0]: D method\n"; $_[0]->NEXT::method() } sub D::AUTOLOAD { print "$_[0]: D AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub D::DESTROY { print "$_[0]: D dtor\n"; $_[0]->NEXT::DESTROY() } package main; my $obj = bless {}, "D"; $obj->method(); # Calls D::method, A::method, C::method $obj->missing_method(); # Calls D::AUTOLOAD, B::AUTOLOAD, C::AUTOLO +AD # Clean-up calls D::DESTROY, B::DESTROY, A::DESTROY, C::DESTROY

Contrary to what the comments above say, when I run this example, the output that I get is:

D=HASH(0x8118164): D method D=HASH(0x8118164): C method D=HASH(0x8118164): D AUTOLOAD D=HASH(0x8118164): B AUTOLOAD D=HASH(0x8118164): C AUTOLOAD D=HASH(0x8118164): D dtor D=HASH(0x8118164): B dtor D=HASH(0x8118164): C dtor

(snip additional question from original c.l.p.mod. posting)

What's the story? Is NEXT really as broken as it looks, or am I missing something? My version of Perl is 5.8.4 and my version of NEXT is 0.60 (the latest one available from CPAN). (-- end J Krugman)

Any thoughts? Thanks.

Jim Keenan

Replies are listed 'Best First'.
Re: Is Conway's NEXT.pm broken?
by !1 (Hermit) on Jan 14, 2005 at 19:49 UTC

    Rename your B package to anything else and it works perfectly.

    use NEXT; package A; sub A::method { print "$_[0]: A method\n"; $_[0]->NEXT::method() } sub A::DESTROY { print "$_[0]: A dtor\n"; $_[0]->NEXT::DESTROY() } package Ba; use base qw( A ); sub Ba::AUTOLOAD { print "$_[0]: B AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub Ba::DESTROY { print "$_[0]: B dtor\n"; $_[0]->NEXT::DESTROY() } package C; sub C::method { print "$_[0]: C method\n"; $_[0]->NEXT::method() } sub C::AUTOLOAD { print "$_[0]: C AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub C::DESTROY { print "$_[0]: C dtor\n"; $_[0]->NEXT::DESTROY() } package D; use base qw( Ba C ); sub D::method { print "$_[0]: D method\n"; $_[0]->NEXT::method() } sub D::AUTOLOAD { print "$_[0]: D AUTOLOAD\n"; $_[0]->NEXT::AUTOLOAD() } sub D::DESTROY { print "$_[0]: D dtor\n"; $_[0]->NEXT::DESTROY() } package main; my $obj = bless {}, "D"; $obj->method(); # Calls D::method, A::method, C::method $obj->missing_method(); # Calls D::AUTOLOAD, B::AUTOLOAD, C::AUTOLO +AD # Clean-up calls D::DESTROY, B::DESTROY, A::DESTROY, C::DESTROY --- D=HASH(0x811b15c): D method D=HASH(0x811b15c): A method D=HASH(0x811b15c): C method D=HASH(0x811b15c): D AUTOLOAD D=HASH(0x811b15c): B AUTOLOAD D=HASH(0x811b15c): C AUTOLOAD D=HASH(0x811b15c): D dtor D=HASH(0x811b15c): B dtor D=HASH(0x811b15c): A dtor D=HASH(0x811b15c): C dtor

    B has special meaning to perl and you shouldn't name any package as such.

    Update: Fooled myself. Basically, what really happens is that use base qw(B C) loads up B.pm which resets @ISA to Exporter. Note that merely changing the use base qw( A ); line to @ISA = "A"; will make the code work the way you want. Of course, base will still load up B.pm and B.pm's loading will set @B::ISA but since @ISA is defined at runtime, everything will work as expected. So there you have it, base is loading up B. If you wish to not touch B.pm at all, you can switch all use base statements to just set @ISA directly or you can create a BEGIN block in which you define either $INC{"B.pm"} or $B::VERSION.

      Submit a documentation bug to TheDamian?

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

      I'm sure if I proposed a module named A.pm, it would never make it into the Perl core. No matter how wonderful it was, I'd be forced to rename it before such a patch would be applied. This is a good thing. Letting such a terrible module name slip through was a bad thing.

      B has special meaning to perl and you shouldn't name any package as such.

      This is an interesting comment, I know that the B modules are used for Backend stuff, but i dont recall ever reading that they have any special meaning beyond that (unlike say the DB package). Can you expand a bit more on this?

      ---
      demerphq