在"从Perl子程序返回一个完整的数组效率低下"的问题中,如果不需要它,两个人建议不要进行优化.作为一般规则,优化可以增加复杂性,如果不需要,简单就更好了.但是在这个特定的情况下,返回一个数组而不是数组ref,我没有看到任何增加的复杂性,我认为接口设计的一致性会更重要.因此,我几乎总是这样做:
sub foo { my($result) = []; #....build up the result array ref $result; }
是否有理由我不应该这样做,即使是小结果?
如果它与接口的其余部分不一致,则不应返回数组引用.如果您使用的其他所有内容都返回列表而不是引用,那么不要让其他程序员记住异常.
除非您有大型列表,否则这实际上是一个微优化问题.如果这是你的计划的瓶颈,你应该很幸运.
就复杂性而言,参考和列表之间的差异远远低于复杂程度,如果程序员正在努力解决这个问题,那么你会遇到更大的问题.复杂的算法和工作流程很复杂,但这只是语法.
说完所有这些之后,我倾向于让所有东西都返回引用并使接口与之一致.
我会在这里从另一个问题复制我的答案的相关部分.
经常忽略的第二个考虑因素是界面.如何使用返回的数组?这很重要,因为整个数组解除引用在Perl中有点糟糕.例如:
for my $info (@{ getInfo($some, $args) }) { ... }
那很难看.这要好得多.
for my $info ( getInfo($some, $args) ) { ... }
它还适用于映射和grepping.
my @info = grep { ... } getInfo($some, $args);
但是,如果要选择单个元素,则返回数组引用可能很方便:
my $address = getInfo($some, $args)->[2];
这比以下更简单:
my $address = (getInfo($some, $args))[2];
要么:
my @info = getInfo($some, $args); my $address = $info[2];
但在那时,您应该质疑@info是真正的列表还是哈希.
my $address = getInfo($some, $args)->{address};
与数组与数组引用不同,没有理由选择在哈希引用上返回哈希值.哈希引用允许方便的简写,就像上面的代码一样.与数组vs refs相反,它使迭代器的情况更简单,或者至少避免了中间变量.
for my $key (keys %{some_func_that_returns_a_hash_ref}) { ... }
你不应该做的是getInfo()
在标量上下文中返回一个数组引用,在列表上下文中返回一个数组.这使得标量上下文的传统使用混乱为阵列长度,这将使用户感到惊讶.
我想补充一点,虽然做一切事情一贯做X是一个很好的经验法则,但它在设计一个好的界面时并不是最重要的.走得太远了,你可以轻松地解决其他更重要的问题.
最后,我将插入我自己的模块,Method :: Signatures,因为它为传入数组引用提供了折衷,而不必使用数组ref语法.
use Method::Signatures; method foo(\@args) { print "@args"; # @args is not a copy push @args, 42; # this alters the caller array } my @nums = (1,2,3); Class->foo(\@nums); # prints 1 2 3 print "@nums"; # prints 1 2 3 42
这是通过Data :: Alias的魔力完成的.
不.除了"返回$ result;" 为清楚起见.
我记得测试过它们的效率,而小型阵列的性能差异很小.对于大型数组,返回引用速度更快.
小结果真的很方便.你愿意这样做吗:
($foo,$bar) = barbaz();
或者返回参考:
$foobar = barbaz(); $foobar->[0]; # $foo $foobar->[1]; # $bar
另一种返回引用的方法:
($foo,$bar) = @{barbaz()};
一般来说,一旦你决定走哪条路,就为你的模块保留它,因为它会让从一种方法切换到下一种方法变得混乱.
我通常返回类似事物列表的数组引用,以及当响应由两到四个不同元素组成时的数组.更重要的是,我做了一个哈希,因为不是所有的调用者都会关心所有的响应元素.