Подтвердить что ты не робот

Что делает `sub bar {+ {$ _ [1] => $_ [2]}}` точно?

Я не понимаю знак сахара + в этом примере, взятый где-то во время просмотра:

sub bar { +{$_[1] => $_[2]} }

Я написал это, и здесь я не вижу различий:

use Data::Dumper;

# Not any differences here
my $foo =  {value => 55};
my $bar = +{value => 55};

print Dumper $foo;
print Dumper $bar;

# Oh ! Here there is something...
sub foo {  {$_[1] => $_[2]} };
sub bar { +{$_[1] => $_[2]} };

print Dumper foo('value', 55);    
print Dumper bar('value', 55);    

foo возвращает

$VAR1 = 55;
$VAR2 = undef;

bar возвращает

$VAR1 = {
          '55' => undef
        };
4b9b3361

Ответ 1

Это помогает анализатору различать анонимный хэш и кодовый блок.

Цитирование Изучение объектов, ссылок и модулей Perl

поскольку блоки и анонимные хэш-конструкторы используют фигурные скобки примерно в тех же местах в дереве синтаксиса, компилятор должен сделать ad hoc определения о том, из какого из двух вы имеете в виду. Если компилятор когда-либо решает неправильно, вам может понадобиться дать подсказку, чтобы получить то, что вы хотите. Чтобы показать компилятору, что вы хотите анонимный хеш-конструктор, поместите знак плюса перед открывающей фигурной скобкой: + {...}. Чтобы получить блок кода, просто поставьте точку с запятой (представляющую пустой оператор) в начале блока: {;...}.

Или из документации по функции map:

"{" starts both hash references and blocks, so "map { ..." could
be either the start of map BLOCK LIST or map EXPR, LIST. Because
Perl doesn't look ahead for the closing "}" it has to take a guess
at which it dealing with based on what it finds just after the
"{". Usually it gets it right, but if it doesn't it won't realize
something is wrong until it gets to the "}" and encounters the
missing (or unexpected) comma. The syntax error will be reported
close to the "}", but you'll need to change something near the "{"
such as using a unary "+" or semicolon to give Perl some help:

    %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 { ("\L$_" => 1) } @array # as does this
    %hash = map {  lc($_) => 1  } @array # and this.
    %hash = map +( lc($_) => 1 ), @array # this is EXPR and works!

    %hash = map  ( lc($_), 1 ),   @array # evaluates to (1, @array)

or to force an anon hash constructor use "+{":

    @hashes = map +{ lc($_) => 1 }, @array # EXPR, so needs
                                           # comma at end

to get a list of anonymous hashes each with only one entry apiece.