Perl keyword requires a strange outcome
I had a problem where my program went into an infinite loop. I narrowed down the problem and it turns out that this keyword is required . So to understand the problem, I wrote a simple hello world program that has an exact file that includes the structure as a large program. It has a main test.pl file that calls helloWorld from test2.pm . test2.pm calls the same routine from test1.pm .
Test.pl
#!/usr/bin/perl
use test1;
use test2;
print "In test\n";
test2::helloWorld();
Test1.pm
#!/usr/bin/perl
package test1;
use test2;
require "test.pl";
@ISA = qw (Exporter);
@Export = qw(
helloWorld
);
sub helloWorld {
print "Hello world: Test1\n";
}
Test2.pm:
#!/usr/bin/perl
package test2;
use test1;
@ISA = qw (Exporter);
@Export = qw(
helloWorld
);
sub helloWorld {
test1::helloWorld();
}
This is the result of the program:
In test
Hello world: Test1
In test
Hello world: Test1
I want to understand why it was printing the result twice? If I comment out the #require "test.pl" from test1.pm it only prints once.
Test1.pm (line comment required)
#!/usr/bin/perl
package test1;
use test2;
#require "test.pl";
@ISA = qw (Exporter);
@Export = qw(
helloWorld
);
sub helloWorld {
print "Hello world: Test1\n";
}
And now this is the result:
In test
Hello world: Test1
I think if I understand this, I can solve my real problem. Thanks for any help in this regard :)
source to share
When a perl script is executed, the files loaded via require
and use
are stored in a hash %INC
to prevent the code from executing more than once, and to prevent endless mutual recursion. However, you are importing your main script from one of the modules it imports, so it will run once during the import process and again as a script. Below is the order of loading and executing your files:
-
test.pl
starts up and sees what it needs to downloadtest1.pm
.-
test1.pm
loads and he sees that he needs to loadtest2.pm
-
test2.pm
is loading and he sees that he needs to downloadtest1.pm
but istest1.pm
already loaded, so he continues. -
test2::helloWorld
is determined andtest2.pm
returned.
-
- Back in
test1
, now he sees what needs to be loadedtest.pl
.- In
test.pl
we are trying to downloadtest1.pm
andtest2.pm
, but they are already loaded throughrequire
. - Print "In test" and challenge
test2::helloWorld
- In
- Come back in
test1.pm
, definetest1::helloWorld
-
- Go back to
test.pl
, type "In test" and calltest2::helloWorld
.
source to share
There are a bunch of bugs in the code, some of which some are unrelated.
- The package name must match the file name
.pm
, including the case.
You are partly moving away from this because you are working with a caseless filesystem (OS X or Windows). use
and require
remember if they have already loaded the module, but they remember the filename, not the module name. When you say use test1
, Perl will search test1.pm
, but load instead test1.pm
. The next time he sees use test1
, he sees that he hasn't downloaded test1.pm
and downloads it again ... and again ... and again.
- Variable to export your function:
@EXPORT
not@EXPORT
.
It matters with variable names.
- The requirement
test.pl
intest1.pm
orTest2.pm
establishes a circular dependency.
This is problem. Perl did not complete compilation test.pl
on load test1.pm
( use
happens at compile time). test1.pm
is compiled and then the download is requested test.pl
( require
happens at runtime), which is what happens. The original compiler then exits test.pl
and runs its code.
You have a similar potential problem because it test1.pm
uses Test2.pm
and Test2.pm
uses test1.pm
.
It's confusing, it's like time travel. Keep it simple: avoid circular dependencies.
There is no reason for Test1.pm to use test.pl. In general, modules should never load a program.
source to share