Как я могу определить, будет ли набор парных скобок в коде Perl действовать как группирующие скобки или формировать список?

В Perl круглые скобки используются для отмены приоритета (как и в большинстве языков программирования), а также для создания списков. Как я могу определить, будет ли определенная пара скобок рассматриваться как группирующая конструкция или как одноэлементный список?

Например, я почти уверен, что это скалярный, а не одноэлементный список: (1 + 1)
А как насчет более сложных выражений? Есть простой способ узнать?


person Ryan C. Thompson    schedule 22.05.2010    source источник
comment
Полагаю, меня больше всего беспокоит случайное присвоение скаляру одноэлементного списка, содержащего результат, вместо самого результата. Но если я правильно читаю ответы, это на самом деле невозможно, если я не сделаю что-то вроде $x = @{[ 1 + 1 ]};. Кажется, что присвоение списка скаляру отличается от присвоения массива скаляру. Что произойдет, если вы назначите скаляр список, содержащий массив? $x = (@list);   -  person Ryan C. Thompson    schedule 23.05.2010
comment
В присвоении левая сторона определяет контекст, в котором будет оцениваться правая сторона. Таким образом, когда вы назначаете массив скалярной переменной, массив оценивается в скалярном контексте. Массив, вычисленный в скалярном контексте, возвращает количество элементов в массиве. Оба примера в вашем комментарии подпадают под эту категорию. Также обратите внимание, что здесь мы говорим об оценке массива в скалярном контексте. Мы не говорим о списке в скалярном контексте, потому что в скалярном контексте нет списков.   -  person FMc    schedule 23.05.2010
comment
Думаю, я всегда считал списки и массивы в основном эквивалентными и взаимозаменяемыми, но это не так.   -  person Ryan C. Thompson    schedule 24.05.2010


Ответы (2)


Здесь полезны три ключевых принципа:

Контекст - главное. Оценка вашего примера (1 + 1) зависит от контекста.

$x = (1 + 1); # Scalar context. $x will equal 2. Parentheses do nothing here.
@y = (1 + 1); # List context. @y will contain one element: (2).
              # Parens do nothing (see below), aside from following 
              # syntax conventions.

В скалярном контексте списка не существует. Чтобы увидеть это, попробуйте присвоить то, что выглядит как список, скалярной переменной. Чтобы подумать об этом, нужно сосредоточиться на поведении оператора запятой: в скалярном контексте он оценивает свой левый аргумент, отбрасывает это значение, затем оценивает свой правый аргумент и возвращает это значение. В контексте списка оператор запятой вставляет оба аргумента в список.

@arr  = (12, 34, 56); # Right side returns a list.

$x    = (12, 34, 56); # Right side returns 56. Also, we get warnings
                      # about 12 and 34 being used in void context.

$x = (@arr, 7);       # Right side returns 7. And we get a warning
                      # about using an array in a void context.

Скобки не создают списки. Оператор запятая создает список (при условии, что мы находимся в контексте списка). При вводе списков в коде Perl круглые скобки необходимы по причинам приоритета, а не по причинам создания списков. Несколько примеров:

  • Скобки не действуют: мы оцениваем массив в скалярном контексте, поэтому правая часть возвращает размер массива.

    $x = (@arr);
    
  • Скобки не нужны для создания списка с одним элементом.

    @arr = 33;         # Works fine, with @arr equal to (33).
    
  • Но круглые скобки необходимы для нескольких элементов - по соображениям приоритета.

    @arr = 12, 34, 56; # @arr equals (12). And we get warnings about using
                       # 34 and 56 in void context.
    
person FMc    schedule 22.05.2010

  1. Контекст.
  2. Скобки не играют той роли, которую, по вашему мнению, они играют в создании списка.

Примеры:

$x = 1 + 1;   # $x is 2.
$x = (1 + 1); # $x is 2.
@x = 1 + 1;   # @x is (2).
@x = (1 + 1); # @x is (2).

$x = (1 + 1, 1 + 2); # $x is 3.
@x = (1 + 1, 1 + 2); # @x is (2, 3).

Грубо говоря, в контексте списка оператор запятой разделяет элементы списка; в скалярном контексте оператор запятой - это «последовательная запятая» C, которая оценивает его левую и правую части и возвращает значение правой стороны. В скалярном контексте круглые скобки группируют выражения для переопределения порядка операций, а в контексте списка круглые скобки делают ... на самом деле то же самое. Причина, по которой они актуальны для присвоения массивам, заключается в следующем:

# Comma has precedence below assignment. 
# @a is assigned (1), 2 and 3 are discarded.
@a = 1, 2, 3; 

# @a is (1, 2, 3).
@a = (1, 2, 3);

Что касается вашего вопроса «это скаляр или одноэлементный список», это просто не имеет смысла задавать изолированное выражение из-за контекста. В контексте списка все является списком; в скалярном контексте ничего нет.

Рекомендуемая литература: perlop, perldata, Программирование на Perl.

person hobbs    schedule 22.05.2010
comment
Мне нравится, когда Депарс показывает этот оператор запятой: perl -MO = Deparse -le 'my @s = 1,3,4; print @s 'BEGIN {$ / = \ n; $ \ = \ n; } my (@s) = 1, '???', '???'; print @s; -e синтаксис ОК - person brian d foy; 22.05.2010