Почему этот блок карты содержит явно бесполезный +?
Во время просмотра исходного кода я увидел следующие строки:
my @files_to_keep = qw (file1 file2);
my %keep = map { + $_ => 1 } @files_to_keep;
Что делает +
в этом фрагменте кода? Я использовал Data::Dumper
, чтобы увидеть, что вынимает знак "плюс", что-то делает, но результаты были одинаковыми:
$ perl cleanme.pl
$VAR1 = {
'file1' => 1,
'file2' => 1
};
Ответы
Ответ 1
Это используется для предотвращения проблемы синтаксического анализа. Символ "плюс" заставляет интерпретатор вести себя как обычный блок, а не выражение.
Страх в том, что, возможно, вы пытаетесь создать hashreference, используя другую (выражение) формулировку map
, как это.
@array_of_hashrefs = map { "\L$_" => 1 }, @array
Обратите внимание на запятую. Тогда, если парсер догадывается, что вы делаете это, учитывая инструкцию в OP, будет синтаксическая ошибка для пропуски запятой! Чтобы увидеть разницу, попробуйте указать "$_"
. По какой-то причине анализатор воспринимает это как достаточно, чтобы вызвать поведение выражения.
Да, это странность. Поэтому многие экстрапараноидальные Perl-программисты бросают в дополнительный знак плюса чаще, чем нужно (включая меня).
Вот примеры из map
документации.
%hash = map { "\L$_" => 1 } @array # perl guesses EXPR. wrong
%hash = map { +"\L$_" => 1 } @array # perl guesses BLOCK. right
%hash = map { ("\L$_" => 1) } @array # this also works
%hash = map { lc($_) => 1 } @array # as does this.
%hash = map +( lc($_) => 1 ), @array # this is EXPR and works!
%hash = map ( lc($_), 1 ), @array # evaluates to (1, @array)
Для забавного чтения (стилистически) и случая, когда парсер ошибается, читайте это: http://blogs.perl.org/users/tom_wyant/2012/01/the-case-of-the-overloaded-curlys.html
Ответ 2
Оператор unary-plus просто возвращает свой операнд без изменений. Добавление одного из них даже не меняет контекста.
В примере, который вы дали, он совершенно бесполезен. Но бывают ситуации, когда это полезно сделать следующий токен то, что, несомненно, является оператором.
Например, map
имеет два синтаксиса.
map EXPR, LIST
и
map BLOCK LIST
Блок начинается с {
, но так же может быть выражение. Например, { }
может быть блочным или хэш-конструктором.
Итак, как map
сказать разницу? Догадывается. Это означает, что иногда это неправильно.
Один случай, когда догадывается неправильно, следующий:
map { $_ => 1 }, @list
Вы можете запрограммировать его правильно, используя +
или ;
.
map {; ... # BLOCK
map +{ ... # EXPR
Итак, в этом случае вы можете использовать
map +{ foo => $_ }, @list
Но я предпочитаю:
map({ foo => $_ }, @list)
Другим примером является то, что вы игнорируете parens вокруг аргументов, а первое выражение выражения начинается с символа.
print ($x+$y)*2; # Same as: 2 * print($x+$y)
Его можно исправить с помощью
print +($x+$y)*2;
Но зачем наваливать на хак, чтобы избежать парнеров? Я предпочитаю
print(($x+$y)*2);