circular use bug?

J

Jim Thomason

I'm strongly leaning towards declaring this a bug and being done with
it, but I wanted to ask here to see if anyone can explain it. I have 2
packages, which use each other.

======
package a
======

package a;

use strict;
use warnings;
use b;

sub foo_a {print "a in foo\n"};


1;


======
package b
======

package b;

use lib '.';
use a qw(from b);

sub foo_b {print "b in foo\n"};

1;

===


All well and good. a uses b. b uses a.

So, here's my connundrum:

[kalel:~] jim% perl -c a.pm
Subroutine foo_a redefined at a.pm line 13.
a.pm syntax OK

But:

[kalel:~] jim% perl -Ma -e '1'
[kalel:~] jim%

Further testing has demonstrated that in all cases I can throw at it, if
I -c a module with a circular use, I get a warning about a redefined
subroutine. However, if I use the module as part of a script, I get no
warning.

Additionally, one thing that I've isolated is that if I use a script,
then %INC is populated immediately. Here:

=====
new package a
=====

package a;

BEGIN {print "BEGINNING IMPORT OF a\n"};
BEGIN {print map {"a> $_ => $INC{$_}\n"} keys %INC};
use strict;
use warnings;
use lib '.';
use b;

sub foo_a {print "a in foo\n"};

1;


#!/usr/bin/perl

use strict;
use warnings;
BEGIN {print map {"w> $_ => $INC{$_}\n"} keys %INC};
use a;


[kalel:~] jim% ./test.pl
w> Exporter.pm => /System/Library/Perl/Exporter.pm
w> Carp.pm => /System/Library/Perl/Carp.pm
w> strict.pm => /System/Library/Perl/strict.pm
w> warnings.pm => /System/Library/Perl/warnings.pm
BEGINNING IMPORT OF a
a> Exporter.pm => /System/Library/Perl/Exporter.pm
a> Carp.pm => /System/Library/Perl/Carp.pm
a> strict.pm => /System/Library/Perl/strict.pm
a> warnings.pm => /System/Library/Perl/warnings.pm
a> a.pm => a.pm

Note that %INC comes in with values.

However,

[kalel:~] jim% perl -c a.pm
BEGINNING IMPORT OF a
BEGINNING IMPORT OF a
a> Exporter.pm => /System/Library/Perl/Exporter.pm
a> Carp.pm => /System/Library/Perl/Carp.pm
a> b.pm => b.pm
a> strict.pm => /System/Library/Perl/strict.pm
a> Config.pm => /System/Library/Perl/darwin/Config.pm
a> warnings.pm => /System/Library/Perl/warnings.pm
a> a.pm => a.pm
a> lib.pm => /System/Library/Perl/lib.pm
Subroutine foo_a redefined at a.pm line 14.
a.pm syntax OK

The first time that a.pm is imported, %INC is unpopulated in any form.
Only once b.pm uses a, does %INC get populated.

Incidentally, best as I can tell, a is used, then b is used, which uses
a. This subsequent use of a compiles the subroutine. b then finishes
compiling and the stack reverts back to compiling a, which re-compiles
the same subroutine. moving the 'use b' line in a to the end of the file
only succeeds in changing the order in which the subroutine is
re-defined (i.e., it's first compiled as part of 'a', then 'b' uses 'a'
and re-compiles it)


Now, to me, this is all rather buggy behavior. Especially considering
the fact that it warns me with -c a.pm but not with my test script (or
-Ma -e '1'

So, is there a clear explanation of this phenomenon? Or should I just
declare it a bug and be done with it?

FWIW, I see the same problem under 5.6.0 on OS X (10.2.6) and 5.8.0
under linux (dunno the distro)

Thanks,

-Jim......
 
S

Sam Holden

[ snip code which is essentially:

a.pm:
package a;
use b;
#...stuff...

b.pm:
package b;
use a;
#...stuff...

]
So, here's my connundrum:

[kalel:~] jim% perl -c a.pm
Subroutine foo_a redefined at a.pm line 13.
a.pm syntax OK

But:

[kalel:~] jim% perl -Ma -e '1'
[kalel:~] jim% [snippage]

Now, to me, this is all rather buggy behavior. Especially considering
the fact that it warns me with -c a.pm but not with my test script (or
-Ma -e '1'

So, is there a clear explanation of this phenomenon? Or should I just
declare it a bug and be done with it?

When you do "perl -c a.pm" you are telling perl to run (well check in this
case) the script a.pm. Perl does that. b.pm gets loaded by the "use b",
then a.pm gets loaded by the "use a". a.pm the "module" and a.pm the
"script", even though they are the same file, are not related to perl.

When you do "perl -Ma -e '1'" a.pm and b.pm both get loaded as modules,
and hence there is no problem.

Perl does not populate %INC with the scipt it is told to run.

The solution is "don't do that". Don't run the a.pm module as a script. If
it doubles as a script then create another file containing "use a;" and use
that as the script.

You will get the same problem without the circular inclusion with:

$ cat c.pm
package c;
sub foo_c { }
1;
$ perl -w -Mc c.pm
Subroutine foo_c redefined at c.pm line 2.
 
B

Bob Walton

Jim said:
I'm strongly leaning towards declaring this a bug and being done with
it, but I wanted to ask here to see if anyone can explain it. I have 2
packages, which use each other.

======
package a
======

package a;

use strict;
use warnings;
use b;

sub foo_a {print "a in foo\n"};


1;


======
package b
======

package b;

use lib '.';
use a qw(from b);

sub foo_b {print "b in foo\n"};

1;

===


All well and good. a uses b. b uses a.

So, here's my connundrum:

[kalel:~] jim% perl -c a.pm
Subroutine foo_a redefined at a.pm line 13.


Your a.pm as shown doesn't have a line 13. ??? You're not putting the
thing you intend as module b into file a.pm also, are you? Oh, now that
I tried it, I see that you did. Modules (as requested in use()
statements) must reside in their own module_name.pm file, because that's
how use() looks for them. The "circular use" should not be an issue as
long as "use a;" isn't executed in a.pm during a "use a;" (or equivalent
like your perl -c a.pm above) that is already in progress (which happens
if you put module b, containing a use a;, in a.pm).

Also, see below for some commentary on the cross-platform consequences
of your unfortunate choice of "b" for a module name.


....
-Jim......

If you were running this on Windoze (yeah, I know, you weren't, but
portability of example programs should be a goal), note that there is
already a package B defined in the standard distribution. Windoze files
are not case-sensitive, so Perl (via Windoze) finds the B module and
uses it when you thought you were asking for your b module. So you
don't pick up the module you thought you were, plus after loading B,
Perl then looks for b and finds nothing, so does nothing. Try renaming
your b.pm to bb.pm and making the package therein be package bb; etc.
That's another variant of the problem that plagues Windoze users when
they use Strict; instead of use strict;, or blow the case of any other
module name.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top