in reply to Circular usage

The code in question:
#a.pl use bspace; use cspace; bgo(); cgo(); #bspace.pm package bspace; use Exporter; use cspace; @ISA='Exporter'; @EXPORT=qw( bgo bhelp ); sub bgo { chelp(); } sub bhelp { print "bhelp\n"; } 1; #cspace.pm package cspace; use Exporter; use bspace; @ISA='Exporter'; @EXPORT=qw( cgo chelp ); sub cgo { bhelp(); } sub chelp { print "chelp\n"; } 1;
Yes, you can do this, but only carefully. You have to make sure that @ISA and @EXPORT are set by the time they are needed. Remember that a use statement temporarily stops compiling the current file while the used file is compiled, executed, and then import called. (If the module had previously been used or required, the compilation and execution is skipped.)

In your case, this is what happens:

a.pl line 1 compiled: "use bspace" bspace line 1 compiled: package bspace; bspace line 2 compiled: use Exporter; Exporter.pm compiled main code of Exporter.pm executed Exporter::->import called (uselessly) bspace line 3 compiled: use cspace; cspace line 1 compiled: package cspace; cspace line 2 compiled: use Exporter; Exporter::import called (uselessly) cspace line 3 compiled: use bspace; bspace::->import called (but doesn't yet exist since bspace::ISA is no +t yet set to inherit import() from Exporter, so bgo and bhelp are not + imported into cspace) cspace line 4 compiled but not executed: @ISA = 'Exporter' cspace line 5 compiled but not executed: @EXPORT = qw(cgo chelp); cspace line 6 compiled: sub cgo { bhelp(); } cspace line 7 compiled: sub chelp { print "chelp\n"; } cspace line 8 compiled but not executed: 1; cspace lines 4,5,8 executed cspace::->import called: cgo and chelp are exported into bspace bspace line 4 compiled but not executed: @ISA = 'Exporter' bspace line 5 compiled but not executed: @EXPORT = qw(bgo bhelp); bspace line 6 compiled: sub bgo { chelp(); } bspace line 7 compiled: sub bhelp { print "bhelp\n"; } bspace line 8 compiled but not executed: 1; bspace lines 4,5,8 executed bspace::->import called: bgo and bhelp are exported into main a.pl line 2 compiled: use cspace cspace::->import called: cgo and chelp are exported into main a.pl line 3 compiled but not executed: bgo() a.pl line 4 compiled but not executed: cgo() a.pl line 3 executed: bgo() (imported from bspace) bspace::bgo calls chelp() (imported from cspace) cspace::chelp prints "chelp\n" a.pl line 4 executed: cgo() (imported from cspace) cspace::cgo calls bhelp() which was not imported from bspace and so do +esn't exist.
So the solution is to start your packages like:
package bspace; use strict; use warnings; use Exporter (); # () avoids (harmless but) useless call to Exporter:: +import; BEGIN { our @ISA = 'Exporter'; our @EXPORT = qw(bgo bhelp); }
and only after that use any modules that might do recursive use. The same technique is needed when putting packages in the same file that use each other, e.g.:
# A.pm package A; use strict; use warnings; use Exporter (); BEGIN { our @ISA = 'Exporter'; our @EXPORT = 'foo' } sub foo { print "foo" } # and in the same file A.pm package A::B; use A; sub bar { foo() } # without the BEGIN block above, the use A won't hav +e imported foo into A::B

Replies are listed 'Best First'.
Re^2: Circular usage
by ysth (Canon) on Nov 23, 2014 at 21:51 UTC
    Nowadays, it is recommended to import 'import' from Exporter instead of inheriting it, so:
    package bspace; use strict; use warnings; use Exporter 'import'; BEGIN { our @EXPORT = qw(bgo bhelp); }