Почему запятая не нужна между аргументами для отображения?

Почему следующее справедливо?

my @ys = map { $_ * $_ } @xs;

А следующие недействительны?

my @ys = map { $_ * $_ }, @xs;

Является ли map языковой конструкцией, а не функцией, или существуют специальные правила для блоков?


person rightfold    schedule 26.09.2013    source источник
comment
Почему в этих ситуациях, потому что Ларри решил сделать это таким образом. :)   -  person brian d foy    schedule 24.12.2013


Ответы (3)


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

Но в целом вам следует избегать прототипов, если вы не знаете, точно что делаете. Как правило, есть лучший способ написать свой код.

person Borodin    schedule 26.09.2013

Да, map — это языковая конструкция.

Например, grep, он поддерживает два разных синтаксиса:

map BLOCK LIST
map EXPR, LIST

BLOCK в вашем примере — простое выражение, поэтому эти два утверждения эквивалентны:

my @ys = map { $_ * $_ } @xs;
my @ys = map $_ * $_, @xs;
person mob    schedule 26.09.2013

Это оператор, и каждый оператор определяет свой собственный синтаксис. 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).

person ikegami    schedule 26.09.2013