Consider the following perl script:
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");
The following code works as expected:
my @student_grades = @grades{ @students };
@student_grades = undef_to_value(@student_grades, 0);
print Dumper(\@student_grades);
# $VAR1 = [
# 100,
# 85,
# 0
# ];
However, trying to pass a hash slice results in 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, but not during a subroutine call?
Is there any way to get the failing example to work as a single assignment?
defined($_) ? $_ : $defaultis usually written$_ // $default. Also note that subroutine prototypes should be avoided because, as you have seen, they almost certainly don't do what you want them to do. They are intended for writing library functions that emulate the behaviour of built-in Perl operators, and that is certainly not what you are doing here.//has been available since 5.10.//, it seems useful. As for avoiding prototypes, the code I'm working on will likely be used and modified by people who aren't terribly perl savvy. Prototypes help me avoid a lot of the guesswork on what kind of edge cases I need to check for.