Почему следующее справедливо?
my @ys = map { $_ * $_ } @xs;
А следующие недействительны?
my @ys = map { $_ * $_ }, @xs;
Является ли map
языковой конструкцией, а не функцией, или существуют специальные правила для блоков?
Почему следующее справедливо?
my @ys = map { $_ * $_ } @xs;
А следующие недействительны?
my @ys = map { $_ * $_ }, @xs;
Является ли map
языковой конструкцией, а не функцией, или существуют специальные правила для блоков?
map
— это оператор списка и основная функция. Это простой синтаксис Perl, который не требует запятой после параметра блока для подпрограммы. Особенность map
в том, что он также может принимать форму map EXPR, LIST
. Если бы это использовалось со стандартной подпрограммой, EXPR
просто оценивалось бы и передавалось как первый параметр.
Параметры блока действительны для всех подпрограмм и могут использоваться, если вы применяете прототипы к определению подпрограммы. Например, вы можете определить mymap
, который ведет себя точно так же, написав
use strict;
use warnings;
use 5.010;
sub mymap(&@) {
use Data::Dump;
my $sub = shift;
my @newlist;
push @newlist, $sub->($_) for @_;
@newlist;
}
say for mymap { $_ * $_ } 1, 2, 3;
вывод
1
4
9
Но в целом вам следует избегать прототипов, если вы не знаете, точно что делаете. Как правило, есть лучший способ написать свой код.
Да, map
— это языковая конструкция.
Например, grep
, он поддерживает два разных синтаксиса:
map BLOCK LIST
map EXPR, LIST
BLOCK
в вашем примере — простое выражение, поэтому эти два утверждения эквивалентны:
my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;
Это оператор, и каждый оператор определяет свой собственный синтаксис. Perl предоставляет инструменты для подпрограмм, которые тоже могут это делать.
Первая строка perlfunc:
Функции в этом разделе могут служить терминами в выражении. Они делятся на две основные категории: операторы списка и именованные унарные операторы.
Таким образом, хотя map
не является функцией в смысле C, они называются подпрограммами в Perl, но это функция по определению Perl.
Итак, map
— это оператор. Многие операторы имеют подпрограммы, которые отличаются от вызовов подпрограмм:
substr
(должны следовать от 1 до 4 выражений, разделенных запятыми)time
(Невозможно указать список аргументов)map BLOCK LIST
print BLOCK LIST
delete HASH_ELEMENT
push ARRAY, LIST
lc
(где указан $_
вызывающей области)EXPR + EXPR
Подпрограммы могут соответствовать или приближаться к синтаксису именованных операторов, используя прототипы (например, sub mypush(\@@)
) и Devel::CallParser (например, loop
).