[Moscow.pm] Особенности парсера?

Maxim Vuets maxim.vuets на gmail.com
Вт Окт 30 13:42:08 PDT 2012


On Wed, Oct 31, 2012 at 12:07:54AM +0400, Vladimir Timofeev wrote:
>perl -e '@A=(1..10); %B=map { "$_"=>1 } @A;'

perl -e '@A=(1..10); %B=map { "$_"=>1 }, @A;'

Только делает оно не то, что ожидалось.

>Первый из них выдает syntax error
>Вопрос, почему?

Компилятор подсказывает:
    Array found where operator expected at -e line 1, near "} "
        (Missing operator before  ?)
        Not enough arguments for map at -e line 1, near "} @A"

map имеет две формы:

    map BLOCK LIST
    map EXPR,LIST

Там же в документации есть большой пример и объяснение:

    "{" 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's 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 "+"
    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 {  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)

    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.

Компилятору показалось, что это EXPR, потому он ожидал запятую.


Подробная информация о списке рассылки Moscow-pm