1;
结尾模块,这样就可以检查调用require函数是否成功。是否可以返回另一个真实值呢?在我的测试中,并没有发现任何问题,但我想知道是否有人遇到过一些问题(比如其他模块或语法或者任何需要该值实际上是1
而不仅仅是true的情况)。编辑:根据大家的意见,由于它只能执行一次(好建议),示例代码已经被删除。似乎共识是可以安全地返回任何真实值,但不能依赖于调用代码返回的值,因为
require
将在第一次加载后返回1
。我已经在我的模块结尾加了一些愚蠢的东西有一段时间了。这没有害处,反而是一个小彩蛋。 uny2k 友好地以 "Yes, this code is a joke."
结束。 Class::Fields 中充满了这种彩蛋。
更进一步,有时当一个函数被记录为返回 true
和 false
时,我会返回一个不是 1 的东西作为 true
。 这是为了惩罚那些写成 if foo() == 1
而实际上他们指的是 if foo()
的人。 这大约是在我编写 use constant TRUE => 1==1; use constant FALSE => !TRUE;
的同一时期。
我曾看到一个模块的返回值在生产代码中被使用过。 我不太记得原因了。 开发者的逻辑很复杂。 我记得他大约是不想只写一行而不是两行。 我不记得他为什么没有导出它。
这是同一个开发者使用 %_
传递参数(*_
符号在跨包范围内是全局的)并在 map 语句中编写了 150 行的 map 语句。
使用返回值的危险除了使程序难以理解外,还有一点,那就是它只能运行一次。
$ cat Foo.pm
package Foo;
return "Basset hounds got long ears";
$ cat test.plx
#!/usr/bin/perl -w
print require Foo, "\n";
print require Foo, "\n";
$ perl -I. test.plx
Basset hounds got long ears
1
require
函数第一次被调用时会评估并返回 Foo.pm 的返回值。第二次调用时,函数检测到该模块已经存在于 %INC
中,只会返回 true 。但是你不能确定你是否是第一个需要引用这个模块的代码。你可以使用 do "Foo.pm"
来绕过这个问题,但现在你每次都重新加载模块,可能会出现重定义函数、性能问题和可能重新初始化全局变量的警告。这不值得。
我认为 (1) 从你的模块返回任意真值没有问题,但是 (2) 对于你建议利用模块实现细节的晦涩难懂且过于聪明的代码来说,存在着一个大问题。不要这样做。
require
成功,那么它需要是一个true 值。如果您不想require
成功(例如,不支持的平台,缺少库),则使用false 值。Mark Dominus,《高阶Perl编程》的作者,解释了我的最爱:
我很少使用
$flag = 'Cogito ergo sum';
,众所周知在所有可能的宇宙中,这是不言而喻的。这确保了最大的可移植性。
目的是,如果您的模块返回false,则require可以在那一点上失败。除了它为真或假之外,没有人关心或依赖于该值。
您应该效仿。您正在使您的模块依赖于实际值,而不仅仅是true或false。例如,在您提供的示例中,如果您的require恰好返回1
,则require将成功,但您聪明的构造函数将失败。
在使用 require
时,你会遇到的一个问题是:它只会在第一次加载该模块时返回模块的返回值。如果该模块已经被加载过了,require
就会直接返回 1,而不会再次加载该模块。
而 do file
语句则会每次重新加载文件,并返回文件的返回值。我曾经使用这个语句将配置数据以匿名散列的形式存储在文件中。
do file
"工作",但是进行错误检查真的很困难。你最好将配置数据存储在一个定义的可解析格式中,比如YAML,而不是直接在一个单独的库中填充数据结构。 - Etherdo $file || die
就足够了。 - Schwern
(require My::Module)->new
这段代码是干什么用的?” :) - Ivan Nevostruev