将散列切片传递给需要数组引用的子例程
Passing hash slice to subroutine expecting array reference
考虑以下 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 );
为什么哈希切片可以通过赋值被哄骗到数组中,而不是在子例程调用期间?
有没有办法让失败的例子作为一个单一的任务来工作?
How is it that a hash slice can be coaxed into an array with assignment
不是。列表上下文中的哈希切片计算为多个标量,列表赋值运算符对此非常满意。
换句话说,
@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 };
\@h{LIST}
等同于 map { $_ } @h{LIST}
.
您可以通过引用然后取消引用任意列表来欺骗原型
undef_to_value( @{[@grades{ @students }]}, 0 );
但这只会修改您输入的副本,因此没有太大帮助。
undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper([@grades{@students}]);
---
$VAR1 = [
100,
85,
undef
];
幸运的是,您的 undef_to_value
函数还 returns 一组更新值,因此您可以说
@grades{@students} = undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper(\%grades);
---
$VAR1 = {
'Bob' => 85,
'Carol' => 92,
'Eve' => 0,
'Alice' => 100
};
考虑以下 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 );
为什么哈希切片可以通过赋值被哄骗到数组中,而不是在子例程调用期间?
有没有办法让失败的例子作为一个单一的任务来工作?
How is it that a hash slice can be coaxed into an array with assignment
不是。列表上下文中的哈希切片计算为多个标量,列表赋值运算符对此非常满意。
换句话说,
@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 };
\@h{LIST}
等同于map { $_ } @h{LIST}
.
您可以通过引用然后取消引用任意列表来欺骗原型
undef_to_value( @{[@grades{ @students }]}, 0 );
但这只会修改您输入的副本,因此没有太大帮助。
undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper([@grades{@students}]);
---
$VAR1 = [
100,
85,
undef
];
幸运的是,您的 undef_to_value
函数还 returns 一组更新值,因此您可以说
@grades{@students} = undef_to_value( @{[@grades{ @students }]}, 0 );
print Dumper(\%grades);
---
$VAR1 = {
'Bob' => 85,
'Carol' => 92,
'Eve' => 0,
'Alice' => 100
};