将哈希切片传递给期望数组引用的子例程

时间:2017-02-07 17:27:34

标签: arrays perl hashmap slice

考虑以下perl脚本:

use strict;
use warnings;
use Data::Dumper;

# Expects an array reference and an undef replacement value
sub undef_to_value(\@$) {
    my $array_ref = shift(@_);
    my $default   = shift(@_);

    # Map each element in the array referenced by $array_ref to...
    #   If the element is defined, itself
    #   Otherwise, the $default value
    return map {
        defined($_) ? $_ : $default
    } @{ $array_ref };
}


my %grades = ("Alice" => 100, "Bob" => 85, "Carol" => 92);
my @students = ("Alice", "Bob", "Eve");

以下代码按预期工作:

my @student_grades = @grades{ @students };
@student_grades = undef_to_value(@student_grades, 0);

print Dumper(\@student_grades);
# $VAR1 = [
#           100,
#           85,
#           0
#         ];

但是,尝试传递哈希切片会导致Type of arg 1 to main::undef_to_value must be array (not hash slice)

my @student_grades = undef_to_value( @grades{ @students }, 0 );

如何将哈希切片同步到具有赋值的数组中,但在子例程调用期间不会? 有没有办法让失败的例子作为单一的任务工作?

2 个答案:

答案 0 :(得分:4)

  

如何将哈希切片同步到具有赋值的数组

不是。列表上下文中的哈希切片评估为多个标量,列表赋值运算符对此非常满意。

换句话说,

@L{qw( a b )} = @R{qw( a b )};

相当于

($L{a}, $L{b}) = ($R{a}, $R{b});

正如您的评论所说,undef_to_value需要数组引用。如果你提供一个数组,原型提供了这个,但你提供的是一个哈希切片。这不是一个变量类型,所以你不能引用它 [1]

只需接受标量:

sub undef_to_value {
    my $default = shift(@_);
    return map { $_ // $default } @_;
}

my @student_grades = undef_to_value(0, @grades{ @students });

当然,你可以简单地使用

my @student_grades = map { $_ // 0 } @grades{ @students };
  1. \@h{LIST}相当于map { \$_ } @h{LIST}

答案 1 :(得分:0)

您可以通过引用然后取消引用任意列表来欺骗原型

undef_to_value( @{[@grades{ @students }]}, 0 );

但这只会修改输入的副本,因此没有用处。

undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper([@grades{@students}]);
---
$VAR1 = [
    100,
    85,
    undef
        ];

幸运的是,您的undef_to_value函数还会返回一组更新值,因此您可以说

@grades{@students} = undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper(\%grades);
---
$VAR1 = {
          'Bob' => 85,
          'Carol' => 92,
          'Eve' => 0,
          'Alice' => 100
        };