insaner
insaner

Reputation: 1705

perl "do" works "require" doesn't: Undefined subroutine

As I have been refactoring some of my code from what someone called "perl 4 coding style" to use packages, I have a question on something I still don't quite fully understand. I know that use includes a file at compile time, and require at runtime (among other differences), both being run as if in the BEGIN section. I know that do is kind of like eval (with some differences).

I have a script (B) that can be run on its own, and I am calling it from another script (C) as a require. Script B calls a require on a .pm file (A) which has just two subs (one to set a variable, and another to return it) and a variable declared as our (I'm guessing my would achieve the same here though). This .pm is not encapsulated with package (hence the situation). If I run script B, it works without a hitch. If I require script B from script C (which also has a require for a package'd .pm that requires A.pm, and uses the accessor func), I get:

Undefined subroutine &main::func_in_A called at script_B

However, if I do A.pm in script_B everything works as expected.

As I was typing up the question, I think I realize what is happening, but let me ask anyway just to make sure.

Is this as a result of the fact that require keeps track of the files it has loaded (while do does not), such that it loads a file exactly once, despite the fact that that once was in the package's namespace, and hence the symbols will not be brought into MAIN when doing a require there? If not, then what am I missing here?

Upvotes: 2

Views: 217

Answers (1)

hobbs
hobbs

Reputation: 240581

Yes, I think that your diagnosis is right. Since A.pm lacks a package statement, subs within it will be defined under whatever package was active when the file was evaluated. Since do has no protection against double-evaluation, A's subs up in two different packages. Since require does, they end up in one package, and which package depends on who loads A first.

Solution: don't use require (and certainly not use) on files without package statements :)

Upvotes: 4

Related Questions