Как уже упоминалось в комментариях, в Perl есть встроенная функция map
, которую вы должны использовать.
my @squares = map {$_ ** 2} 1 .. 5;
Вместо передачи аргумента, встроенная в Perl map
устанавливает $_
для каждого элемента, что позволяет вам писать вашу square
функцию кратко как {$_ * $_}
или {$_ ** 2}
Но Perl также дает вам возможность создавать пользовательские функции, подобные карте с аналогичным синтаксисом.Например, предположим, что вы хотите написать версию map
, которая отображает пары значений:
sub pair_map (&@) { # the (&@) prototype here tells perl that the sub
my $code = shift; # takes a code block, and then a list, just like `map`
my @ret;
while (@_) {
push @ret, $code->(splice @_, 0, 2);
}
@ret
}
my @pairs = pair_map {\@_} 1 .. 10;
pair_map {print "$_[0]: $_[1]\n"} %hash;
Но поскольку Perl уже давно, большинство служебных функций, вероятно, уже написаны.Поиск CPAN приведет к появлению многих map
-подобных функций, выполняющих различные операции.
Я обнаружил, что мне часто приходится отображать списки с различными размерами шагов, поэтому я написал функцию mapn
в Список :: Gen .Это полностью разработанное решение, поэтому оно включает в себя оптимизацию при вызове в пустом контексте и возвращается к собственному Perl map
, когда n == 1
:
sub mapn (&$@) {
my ($sub, $n, @ret) = splice @_, 0, 2;
croak '$_[1] must be >= 1' unless $n >= 1;
return map $sub->($_) => @_ if $n == 1;
my $want = defined wantarray;
while (@_) {
local *_ = \$_[0];
if ($want) {push @ret =>
$sub->(splice @_, 0, $n)}
else {$sub->(splice @_, 0, $n)}
}
@ret
}
Оба pair_map
и mapn
используютрасширенная функция подпрограмм Perl, называемая прототипами.Эти прототипы не являются инструментами проверки аргументов (как во многих других языках).Скорее, они говорят Perl интерпретировать вызовы функций особым образом (аналогично тому, как используются некоторые другие встроенные функции).В этом случае, часть &
прототипа сообщает Perl, что первый аргумент этих функций может быть записан как пустой блок, как обычный вызов map
.