我思索最佳实践进行数据传递哈希引用,以便返回到/从功能。
在一方面,它似乎直观只输入值传递给函数,只返回输出变量。 然而,在Perl哈希值传递只能通过参考来完成,所以这是一个有点乱,似乎更多的是机会,犯了一个错误。
另一种方式是通过在输入变量的参考,但随后它与在函数处理,而这可能不是很清楚什么是输入,什么是返回变量。
什么是对此最好的做法?
返回引用数组和散列,然后解除引用它。
($ref_array,$ref_hash) = $this->getData('input');
@array = @{$ref_array};
%hash = %{$ref_hash};
通过参考文献(@array,哈希%),以将保持输出数据的功能。
$this->getData('input', \@array, \%hash);
Answer 1:
只返回引用。 有没有必要取消引用整个哈希就像你在你的例子都在做:
my $result = some_function_that_returns_a_hashref;
say "Foo is ", $result->{foo};
say $_, " => ", $result->{$_} for keys %$result;
等等
我从来没有见过任何人传递空引用保存结果。 这是Perl的,而不是C.
Answer 2:
试图通过说创建副本
my %hash = %{$ref_hash};
甚至比使用hashref更危险。 这是因为它只是创建了一个浅拷贝。 这将导致你思维它是好的,修改散列,但是如果它包含引用,他们会修改原始数据结构。 我觉得最好还是通过引用和小心,但如果你真的要确保你有你可以说通过引用的副本:
use Storable qw/dclone/;
my %hash = %{dclone $ref_hash};
Answer 3:
第一个是更好的:
my ($ref_array,$ref_hash) = $this->getData('input');
其理由是:
- 在第二种情况下,的getData()需要检查的数据结构,以确保它们是空的
- 你能自由地返回undef特殊值
- 它看起来更Perl的成语。
注:该线
@array = @{$ref_array};
%hash = %{$ref_hash};
是有问题的,因为你在这里浅复制整个数据结构。 >运营商为了方便 - 在您需要阵列/散列,使用你到处都可以使用的引用。
Answer 4:
如果它变得足够复杂,无论是调用点和被调用函数是它(每次使用它的时候,因为你必须要考虑/写更多),为什么不直接使用一个对象支付?
my $results = $this->getData('input');
$results->key_value_thingies;
$results->listy_thingies;
如果制作一个对象是“太复杂”,然后开始使用驼鹿,使其不再是。
Answer 5:
我个人偏爱子接口:
- 如果例程具有0-3参数,它们可以以列表的形式被传递:
foo( 'a', 12, [1,2,3] );
- 否则,通过名称值对的列表。
foo( one => 'a', two => 12, three => [1,2,3] );
- 如果程序具有或者可能具有多个参数认真考虑使用名称/值对。
参考文献传递无意中增加数据修改的风险。
在回报我一般喜欢返回结果的列表,而不是一个数组或散列引用。
我返回散列或阵列裁判时就会使在速度或存储器消耗(即BIG结构)时,或者当一个复杂的数据结构涉及明显的改善。
不需要的时候返回引用剥夺了利用Perl的很好的列表处理功能优势的能力之一,并公开了一个数据的意外修改的危险。
特别是,我发现它有用结果的列表分配到一个数组和返回数组,它提供了一个数组我潜艇的上下文回报的行为。
对于传入两个散列我会做一些这样的情况:
my $foo = foo( hash1 => \%hash1, hash2 => \%hash2 ); # gets number of items returned
my @foo = foo( hash1 => \%hash1, hash2 => \%hash2 ); # gets items returned
sub foo {
my %arg = @_;
# do stuff
return @results;
}
Answer 6:
我最初发布这一个问题,然后有人指出,这是一个“相关的帖子”,所以我会在这里张贴我就这个题目,假定人们会遇到它的未来。
我要去顶撞接受的答案,并说,我希望有我的返回数据作为一个普通的哈希(当然,作为偶数大小的列表,它很可能被解释为一个哈希)。 我在哪里,我们倾向于做的事情,如下面的代码片段的环境中工作,它更容易结合起来,并进行排序和切片和切块时,你不必提领每隔一行。 (这也是不错知道,因为你按值传递整个事情的人不能破坏你的hashref - 尽管有人指出,如果你的散列包含比简单的标量更是没那么简单)
my %filtered_config_slice =
hashgrep { $a !~ /^apparent_/ && defined $b } (
map { $_->build_config_slice(%some_params, some_other => 'param') }
($self->partial_config_strategies, $other_config_strategy)
);
这接近的东西,我的代码可能会做:建立一个基于不同的配置策略对象的对象(其中一些对象知道本身,再加上一些额外的家伙)一个配置,然后过滤掉其中的一些不相干。
(是的,我们有很好的工具,如hashgrep
和hashmap
和lkeys
是做有用的事情给哈希。$ a和$ b被置为关键和每个项目的列表中的数值,分别)。 (是的,我们的人谁能够在这个级别进行编程。招聘是很厉害的,但我们有一个优质的产品。)
如果你不打算做任何类似这样的函数式编程,或者如果你需要更高的性能(你异形?)然后确定,使用hashrefs。
Answer 7:
呃......“经过哈希只能通过参考做”?
sub foo(%) {
my %hash = @_;
do_stuff_with(%hash);
}
my %hash = (a => 1, b => 2);
foo(%hash);
我在想什么?
我会说,如果该问题是,你需要从一个函数有多个输出,这是作为一般的做法是输出的数据结构,可能是一个哈希更好,保存您需要发送出去,而不是采取修改引用作为参数一切。
文章来源: What's the best Perl practice for returning hashes from functions?