什么是最好的Perl的做法从函数返回的哈希?(What's the best Perl pr

2019-07-29 19:01发布

我思索最佳实践进行数据传递哈希引用,以便返回到/从功能。

在一方面,它似乎直观只输入值传递给函数,只返回输出变量。 然而,在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:

我个人偏爱子接口:

  1. 如果例程具有0-3参数,它们可以以列表的形式被传递: foo( 'a', 12, [1,2,3] );
  2. 否则,通过名称值对的列表。 foo( one => 'a', two => 12, three => [1,2,3] );
  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)
);

这接近的东西,我的代码可能会做:建立一个基于不同的配置策略对象的对象(其中一些对象知道本身,再加上一些额外的家伙)一个配置,然后过滤掉其中的一些不相干。

(是的,我们有很好的工具,如hashgrephashmaplkeys是做有用的事情给哈希。$ 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?