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 :)

+3


source to share


2 answers


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 download test1.pm

    .
    • test1.pm

      loads and he sees that he needs to load test2.pm

      • test2.pm

        is loading and he sees that he needs to download test1.pm

        but is test1.pm

        already loaded, so he continues.
      • test2::helloWorld

        is determined and test2.pm

        returned.
    • Back in test1

      , now he sees what needs to be loaded test.pl

      .
      • In test.pl

        we are trying to download test1.pm

        and test2.pm

        , but they are already loaded through require

        .
      • Print "In test" and challenge test2::helloWorld

    • Come back in test1.pm

      , definetest1::helloWorld

  • Go back to test.pl

    , type "In test" and call test2::helloWorld

    .
+4


source


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

    in test1.pm

    or Test2.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.

+3


source







All Articles