Как работают скобки в Perl 5? - PullRequest
1 голос
/ 14 июля 2011

Вот сеанс Devel :: REPL (моя версия Perl v5.10.1). Не могли бы вы объяснить результаты, пожалуйста?

0:main$ my $x = 1,2,4
[
  1,
  2,
  4
]

0:main$ my $y = (1,2,4)
Useless use of a constant in void context at (eval 296) line 8.
4

Я только начинаю изучать Perl и все еще испытываю проблемы с поиском контекстов. В любом случае, я думаю, что понимаю, почему второе задание делает то, что делает. Это потому, что у нас есть скалярный контекст, поэтому никакой список не создается вообще, и мы просто заканчиваем тем, что выполняем оператор запятой несколько раз, в то время как этот оператор просто возвращает свой правильный операнд. Правильно?

Однако, что не так с первым заданием? Разве это не должно быть эквивалентно второму? В какой-то момент я подумал, что круглые скобки не предоставляют никакой магической семантики для создания списков - они просто группируют элементы вместе, и если элементы в конечном итоге используются в контексте списка, они просто преобразуются в список. Видимо, это не так.

Хорошо, хорошо. Какова же особая роль скобок?

Ответы [ 2 ]

6 голосов
/ 14 июля 2011

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

 say join ', ' => do {my $x = 1, 2, 4}

Что анализируется как:

 say join ', ' => do {(my $x = 1), (2), (4)}

И поэтому REPL печатает «1, 2, 4», поскольку он получил 3 значения из блока do.

Вторая строка:

 say join ', ' => do {my $x = (1, 2, 4)}

Который анализируется как:

 say join ', ' => do {(my $x = scalar(1, 2, 4))}

Список в скалярном контексте возвращает свой последний элемент, который присваивается $x, а затем возвращается блоком do, после чего выводится «4».

5 голосов
/ 14 июля 2011

Я думаю, что поведение первого оператора является результатом Devel::REPL, но в данный момент у меня нет его для проверки этого предположения.

Скобки в Perl в первую очередь корректируют приоритет.Они также могут регулировать то, как синтаксический анализатор видит некоторые операторы, но здесь это не так.= имеет более высокий приоритет, чем ,, поэтому в первом операторе, если Devel::REPL оценивает операторы в контексте списка, он анализируется как список, где первый элемент является результатом присваивания от 1 до $xа второе и третье значения равны 2 и 4. Во втором порядке был изменен приоритет, и в результате контекст изменился так, что , находится в скалярном контексте, а 4 присвоено $x.

$ perl -MO=Deparse,-p -e 'my $x = 1,2,4'
((my $x = 1), '???', '???');
-e syntax OK

$ perl -MO=Deparse,-p -e 'my $x = (1,2,4)'
(my $x = ('???', '???', 4));
-e syntax OK

Я бы поспорил, если вы наберете scalar(my $x = 1,2,4) в Devel::REPL, результат будет 4, а $x будет равен 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...