Last Updated: February 25, 2016
·
2.28K
· kablamo

Resolve circular dependencies with Carp::Always

Circular dependencies happen when your library requires a library which requires your library. Here's an example. Lets say you have 2 packages:

AlienPlanet.pm

package AlienPlanet;
use Moose;
use Dinosaurs;          # <--- Circular dependency
sub has_dinosaurs {1}
1;

Dinosaurs.pm

package Dinosaurs;
use Moose;
use AlienPlanet;        # <--- Circular dependency
sub has_rabies {1}
1;

If you try to compile this, you get the following warning:

⚡ perl -c AlienPlanet.pm 
Subroutine has_dinosaurs redefined at AlienPlanet.pm line 5.
AlienPlanet.pm syntax OK

In this case its obvious where the problem is.

But if the package you included, included 25 other libraries, which included other libraries, which included your original library -- then its harder to figure out where the circle is.

Happily I discovered a good solution. First, modify AlienPlanet.pm to look like this:

package AlienPlanet;
sub has_dinosaurs {1}   <-- swap
use Dinosaurs;          <-- swap
1;

Next, try compiling your code again but this time with Carp::Always:

⚡ perl -MCarp::Always -c AlienPlanet.pm
Subroutine has_dinosaurs redefined at AlienPlanet.pm line 4.
        require AlienPlanet.pm called at Dinosaurs.pm line 4
        Dinosaurs::BEGIN() called at AlienPlanet.pm line 4
        eval {...} called at AlienPlanet.pm line 4
        require Dinosaurs.pm called at AlienPlanet.pm line 5
        AlienPlanet::BEGIN() called at AlienPlanet.pm line 4
        eval {...} called at AlienPlanet.pm line 4
AlienPlanet.pm syntax OK

Now you've got a stack trace and its easy to see where your problem is. All thats left is figuring out how to solve it. (Fast solution: use Class::Load in the Dinosaurs package.)

Cross posted on blog.kablamo.org