perl hash ref return: { 'a' =>1, % { sub() } }

jkl*_*jkl 1 perl hash return reference

{ 'a' =>1, % { sub() } }
Run Code Online (Sandbox Code Playgroud)

这是否最适合将作为 ref 返回的哈希包含在其他中?

%$sub() 不起作用。

就我而言, new {} 生成新的散列并返回引用,可能是 new 优化了这种情况,但不确定。

bri*_*foy 5

我猜您有一些返回散列引用的子例程,并且您希望将所有这些键包含在更大的散列中:

my $hash_ref = some_sub(...);
my $big_hash = { a => 1 };
Run Code Online (Sandbox Code Playgroud)

有几种方法可以做到。在您的问题中,您似乎试图通过取消引用返回值来内联进行。这可能是合理的。环绕符号或后缀解引用可以做到这一点:

# general circumfix (old way)
my $big_hash = { a => 1, %{ some_sub() } };

# postfix dereference (new v5.24 hotness)
my $big_hash = { a => 1, some_sub()->%* };
Run Code Online (Sandbox Code Playgroud)

但是,我倾向于不喜欢直接这样做。通常,当存在可能被以下内容覆盖的默认值时,我会这样做some_sub()

my %defaults = ( ... );

my %big_hash = ( %defaults, some_sub()->%* );
Run Code Online (Sandbox Code Playgroud)

但是,我通常更进一步,将产生默认值的东西放到另一个子程序中,这样我就可以给子类一个覆盖它的方法:

sub defaults {
   my %defaults = ( ... );
   return \%defaults;
   }

my %big_hash = ( defaults()->%*, some_sub()->%* );
Run Code Online (Sandbox Code Playgroud)

还有许多其他方法可以合并哈希。有如何在 Perl 中组合散列?在 StackOverflow 上,还有如何在 perlfaq4 中合并两个哈希值

但是,还有另一件事需要考虑。简单地将两个哈希混合在一起以获得一个新的哈希可能会很昂贵。如果第一个散列非常非常大怎么办?

my %grand_hash = ( %very_big_hash, %new_hash );
Run Code Online (Sandbox Code Playgroud)

人们经常这样做并分配回起始哈希,主要是因为它很容易输入:

my %grand_hash = ( %grand_hash, %new_hash );
Run Code Online (Sandbox Code Playgroud)

您告诉 Perl 展开%grand_hash,将另一个列表与其组合,然后重新散列这个巨大的列表。

虽然有点笨拙,但更好的方法是添加新的键和值。

foreach my $new_key ( keys %new_hash ) {
    $grand_hash{$new_key} = $new_hash{$new_key};
    }
Run Code Online (Sandbox Code Playgroud)

当您需要做其他事情时,这很好,例如跳过哈希中已有的键:

foreach my $new_key ( keys %new_hash ) {
    next if exists $grand_hash{$new_key};
    $grand_hash{$new_key} = $new_hash{$new_key};
    }
Run Code Online (Sandbox Code Playgroud)

或者可能添加到已经存在的值而不是替换它:

foreach my $new_key ( keys %new_hash ) {
    $grand_hash{$new_key} += $new_hash{$new_key};
    }
Run Code Online (Sandbox Code Playgroud)

如果您只需要添加它而不关心替换值,那么哈希切片非常适合同时分配多个键和值:

@grand_hash{ keys %new_hash } = values %new_hash;
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您将调用一次子例程并存储结果,这样您就不必再次构造哈希。然后您取消引用该哈希是切片(或您想使用它的任何地方:

my $new_hash = some_sub(...);
@grand_hash{ keys %$new_hash } = values %$new_hash;
Run Code Online (Sandbox Code Playgroud)