由于我一直在从别人所说的"perl4编码风格"重构我的一些代码,以使用package
s,我有一个问题,我仍然不完全理解。我知道use
在编译时包含一个文件,在运行时包含require
(以及其他差异),两者都像在BEGIN
部分中一样运行。我知道do
有点像eval
(有一些不同)。
我有一个可以单独运行的脚本(B),我从另一个脚本(C)中调用它作为require
Script B在.pm文件(a)上调用一个require
,该文件只有两个子(一个用于设置变量,另一个用于返回变量)和一个声明为our
的变量(我猜my
在这里也会实现同样的效果)。这个.pm不是用package
封装的(因此是这种情况)。如果我运行脚本B,它可以顺利运行。如果我从脚本C(它也有一个require
用于package
'd.pm,即require
s a.pm,并使用访问函数)中选择require
剧本B,我得到:
Undefined subroutine &main::func_in_A called at script_B
但是,如果script_B中的I do
A.pm,则一切正常。
当我输入这个问题时,我想我意识到发生了什么,但无论如何让我问一下,只是为了确定一下。
这是因为require
会跟踪它加载的文件(而do
不会),因此它只加载一次文件,尽管那一次在包的命名空间中,因此在那里执行require
时,符号不会进入MAIN吗?如果没有,那么我在这里错过了什么?
是的,我认为你的诊断是正确的。由于A.pm缺少package
语句,因此它中的子语句将在评估文件时处于活动状态的任何包下定义。由于do
没有防止双重评估的保护,A的潜艇分为两个不同的包。由于require
是这样做的,所以它们最终在一个包中,而哪个包取决于谁先加载A。
解决方案:不要在没有package
语句的文件上使用require
(当然也不要使用use
):)