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

AFAIK, Perl itself has no problems with a use of circular dependencies between classes (not modules which export stuff at compile time), and circular dependencies are pretty valid design pattern in some cases (ORM)

Now I found problem using it in Moose:

(this one ok)

$ perl -MAA -e 'AA->mysub()' AA BB

(this fails)
perl -MBB -e 'AA->mysub()' The method 'mysub' was not found in the inheritance hierarchy for AA a +t /usr/local/lib/perl/5.14.2/Class/MOP/Class.pm line 1053. Class::MOP::Class::__ANON__(Moose::Meta::Class=HASH(0x202fc18), "m +ysub") called at /usr/local/lib/perl/5.14.2/Class/MOP/Class.pm line 1 +098 Class::MOP::Class::add_around_method_modifier(Moose::Meta::Class=H +ASH(0x202fc18), "mysub", CODE(0x202b7b0)) called at /usr/local/lib/pe +rl/5.14.2/Moose/Util.pm line 267 Moose::Util::add_method_modifier(Moose::Meta::Class=HASH(0x202fc18 +), "around", ARRAY(0x1edb158)) called at /usr/local/lib/perl/5.14.2/M +oose.pm line 93 Moose::around(undef, "mysub") called at /usr/local/lib/perl/5.14.2 +/Moose/Exporter.pm line 409 Moose::around("mysub", CODE(0x202b7b0)) called at AA.pm line 11 require AA.pm called at CC.pm line 3 CC::BEGIN() called at AA.pm line 0 eval {...} called at AA.pm line 0 require CC.pm called at BB.pm line 4 BB::BEGIN() called at AA.pm line 0 eval {...} called at AA.pm line 0 require BB.pm called at -e line 0 main::BEGIN() called at AA.pm line 0 eval {...} called at AA.pm line 0 Compilation failed in require at CC.pm line 3. BEGIN failed--compilation aborted at CC.pm line 3. Compilation failed in require at BB.pm line 4. BEGIN failed--compilation aborted at BB.pm line 4. Compilation failed in require. BEGIN failed--compilation aborted.
AA.pm:
package AA; use utf8; use Moose; use CC; extends 'BB'; around mysub => sub { print "AA\n"; shift->(); };
BB.pm:
package BB; use utf8; use Moose; use CC; sub mysub { print "BB\n";}
CC.pm:
package CC; use AA; 1;

I think that's because Moose tries to find symbols during compile time. Pure perl does not seem to have same problem:
$ perl -MBB -e 'AA->mysub()' AA BB
AA.pm:
package AA; use utf8; use CC; use parent 'BB'; sub mysub { print "AA\n"; shift->SUPER::mysub(); };
BB.pm:
package BB; use utf8; use CC; sub mysub { print "BB\n";} 1;
CC.pm:
package CC; use AA; 1;

Question is: how to treat this? A bug? Design limitation? What to do in case I want to use circular dependencies? Is there a workaound?

Replies are listed 'Best First'.
Re: Moose support for circular dependencies?
by ikegami (Patriarch) on Apr 13, 2015 at 13:56 UTC
    Do as you would in other languages: Declare symbols before using them.
    package BB; use utf8; use Moose; sub mysub; use CC; sub mysub { print "BB\n";}
    or
    package BB; use utf8; use Moose; sub mysub { print "BB\n";} use CC;

    Note that you can have the same problem in Perl without Moose if you export or if you have prototypes.

      Ok, thanks, that indeed works!
      as for export/prototypes - yes, I know.
Re: Moose support for circular dependencies?
by choroba (Cardinal) on Apr 13, 2015 at 14:02 UTC
    You don't have to call the sub to see the error, the same happens for
    perl -MBB -e1

    Interestingly, moving use CC; to the bottom in BB.pm (or predeclaring sub mysub before using CC) solves the problem.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ