什么是有效的Perl模块返回值?

16
在Perl中,通常的做法是以1;结尾模块,这样就可以检查调用require函数是否成功。是否可以返回另一个真实值呢?在我的测试中,并没有发现任何问题,但我想知道是否有人遇到过一些问题(比如其他模块或语法或者任何需要该值实际上是1而不仅仅是true的情况)。
编辑:根据大家的意见,由于它只能执行一次(好建议),示例代码已经被删除。似乎共识是可以安全地返回任何真实值,但不能依赖于调用代码返回的值,因为require将在第一次加载后返回1

你为什么想要这样做? - innaM
3
我讨厌重复打同样的东西。我同意,我有一个重构的问题,我一直在参加会议... - Eric Strom
7
重构和高尔夫是两回事。;) - Adam Bellaire
4
如果您不喜欢打字,为什么要返回一个包名而不是一个对象? :) - brian d foy
3
将来有一天,我们可能会在Stack Overflow上看到这样一个问题:“(require My::Module)->new 这段代码是干什么用的?” :) - Ivan Nevostruev
我很想发布那个问题,但是还没有勇气。 - Jonathan Feinberg
6个回答

17

我已经在我的模块结尾加了一些愚蠢的东西有一段时间了。这没有害处,反而是一个小彩蛋。 uny2k 友好地以 "Yes, this code is a joke." 结束。 Class::Fields 中充满了这种彩蛋。

更进一步,有时当一个函数被记录为返回 truefalse 时,我会返回一个不是 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" 来绕过这个问题,但现在你每次都重新加载模块,可能会出现重定义函数、性能问题和可能重新初始化全局变量的警告。这不值得。


8

我认为 (1) 从你的模块返回任意真值没有问题,但是 (2) 对于你建议利用模块实现细节的晦涩难懂且过于聪明的代码来说,存在着一个问题。不要这样做。


7
任何东西都可以作为有效的返回值。如果您希望require成功,那么它需要是一个true 值。如果您不想require成功(例如,不支持的平台,缺少库),则使用false 值。
要查看其他人所使用的返回值,请查看Acme::ReturnValue
人们不希望将返回值用于任何事情,因此我不会尝试这样做,无论当时多聪明。:)

6

Mark Dominus,《高阶Perl编程》的作者,解释了我的最爱:

我很少使用 $flag = 'Cogito ergo sum';,众所周知在所有可能的宇宙中,这是不言而喻的。这确保了最大的可移植性。


4

目的是,如果您的模块返回false,则require可以在那一点上失败。除了它为真或假之外,没有人关心或依赖于该值。

您应该效仿。您正在使您的模块依赖于实际值,而不仅仅是true或false。例如,在您提供的示例中,如果您的require恰好返回1,则require将成功,但您聪明的构造函数将失败。


1

在使用 require 时,你会遇到的一个问题是:它只会在第一次加载该模块时返回模块的返回值。如果该模块已经被加载过了,require 就会直接返回 1,而不会再次加载该模块。

do file 语句则会每次重新加载文件,并返回文件的返回值。我曾经使用这个语句将配置数据以匿名散列的形式存储在文件中。


do file "工作",但是进行错误检查真的很困难。你最好将配置数据存储在一个定义的可解析格式中,比如YAML,而不是直接在一个单独的库中填充数据结构。 - Ether
@Ether 我可以想到不将配置信息放入Perl数据结构中的原因(它是不安全和不可移植的),但错误检查不是其中之一。Perl会为您进行检查。do $file || die就足够了。 - Schwern

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接