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

The following code produces a circular class hierarchy. (Yes, I know that's a no-no, but that's not the point.)
#!/usr/bin/perl use strict; use warnings; package aaa; { our @ISA = 'bbb'; sub new { return bless {}, shift; } } package bbb; { our @ISA = 'aaa'; sub new { return bless {}, shift; } } package main; my $obj = bbb->new;
When run, it produces the following error message:
Recursive inheritance detected while looking for method '()' in package 'bbb'.
From other testing I did, I determined that the method being referred to in the error message is not DESTROY even though the error occurs when the object goes out of scope.

Further, I determined that the method name is not an empty string. Perl is literally looking for a method called '()'.

The question is: Just what is this strange method '()'?


Remember: There's always one more bug.

Replies are listed 'Best First'.
Re: What is method () ?
by diotalevi (Canon) on Oct 05, 2005 at 16:19 UTC

    The () method is used internally by the overload module.

Re: What is method () ?
by Perl Mouse (Chaplain) on Oct 05, 2005 at 16:01 UTC
    Sounds like a data corruptions to me. It even gets weirder. I added the following to your code:
    BEGIN { use Carp; no strict 'refs'; *{"bbb::()"} = sub {confess}; }
    That resulted in:
    Recursive inheritance detected while looking for method '(abs' in pack +age 'bbb'.
    Removing the BEGIN block again, and running your program with the -Do flag to perl gives:
    (/opt/perl/lib/5.8.6/base.pm:74) Looking for method isa in pack +age aaa (/opt/perl/lib/5.8.6/base.pm:74) Looking for method isa in pack +age UNIVERSAL (/opt/perl/lib/5.8.6/base.pm:74) Looking for method isa in pack +age bbb (/opt/perl/lib/5.8.6/base.pm:74) Looking for method isa in pack +age UNIVERSAL EXECUTING... (xx:0) Recalcing overload magic in package bbb (xx:0) Looking for method () in package bbb (xx:0) Looking for method () in package aaa (xx:0) Looking for method () in package bbb (xx:0) Looking for method () in package aaa .... (xx:0) Looking for method () in package bbb (xx:0) Looking for method () in package aaa Recursive inheritance detected while looking for method '()' in packag +e 'bbb'. (xx:0) Recalcing overload magic in package IO::Handle (xx:0) Looking for method () in package IO::Handle (xx:0) Looking for method () in package UNIVERSAL (xx:0) Checking overloading of `DESTROY' in package `IO::Handle' (xx:0) Looking for method DESTROY in package IO::Handle (xx:0) Looking for method DESTROY in package UNIVERSAL (xx:0) Looking for method AUTOLOAD in package IO::Handle (xx:0) Looking for method AUTOLOAD in package UNIVERSAL
    Perl --((8:>*
Re: What is method () ?
by revdiablo (Prior) on Oct 05, 2005 at 17:53 UTC

    Completely unrelated to the topic at hand, I noticed you have your packages declared with:

    package foo; { ... }

    Which I don't really understand. It makes it look almost like the package is defined within the block. But it's really a bare block with a package declaration just before it. That means the package declaration won't be limited to the block, as it would with something like:

    { package foo; ... }

    So while your style looks nice, I think it might be misleading, and I'm wondering if there's any reason you use it that I'm not thinking of.

      From Perl Best Practices, pg. 328:
      That block is vital, because it creates a limited scope,
      to which any lexical variables that are declared as part
      of the class will automatically be restricted.
      
      The benefits are then explained later on pg. 330-332.

      Remember: There's always one more bug.

        It's true that the block will limit the scope of lexical variables, but my point is that the code you have won't limit the scope of the package declaration. We can see how the package is still changed, even after the block ends:

        package foo; { print __PACKAGE__; # prints "foo" } print __PACKAGE__; # also prints "foo"

        But compare this, where the package is only changed within the block:

        { package foo; print __PACKAGE__; # prints "foo" } print __PACKAGE__; # prints "main"

        Unless there is some strong further justification in the book (which I would be interested to see, but not interested enough to pay for it), I remain unpersuaded.

        I don't know the context that TheDamian wrote that in, but I would consider it to be misleading as posted here.

        When you have a single package declared in a file there is no need for the braces. The file is a single enclosing lexical scope so the braces are unnecessary, and even possibly confusing.

        OTOH, when you have a mutliple packages declared in a file then you should use the braces as it enforces lexical seperation between the package implementations. But the thing is you probably should put the package declaration inside of the braces and not outside.

        But that leads to the question of why you would put mutliple packages in a single file. I know of a few reasons to do so, but IME its rare that they come up.

        ---
        $world=~s/war/peace/g

        TheDamian's benefits relate to hashes scoped to the block that are used hold the attributes of instances to the class, making them properly declared and truly private.

        The block is redundant in your code as no such variables exist, and your classes appear to be using the usual idiom of blessing an anonymous hash to store attributes, whereas TheDamian's code blesses an anonymous scalar so that this idiom can't be used.

        Roger_B

Re: What is method () ?
by ikegami (Patriarch) on Oct 05, 2005 at 16:11 UTC

    You say that bbb isa aaa, and that aaa isa bbb. That makes no sense, and it's the root cause of that error.

    Update: Oops, you already knew that (and have since updated your node to say so explicitely). Ignore above.

    Update: So I dug some more. Based on the message "Recalcing overload magic in package XXX", I checked overload. There's definitely a reference to () in the source, relating to the fallback special overload. It doesn't seem to be called by overload itself.