Perl: приоритет (оператор списка слева) - PullRequest
1 голос
/ 17 февраля 2011

из Programming Perl pg 90, он говорит:

   @ary = (1, 3, sort 4, 2);
    print @ary;

запятые справа от сортировки оцениваются перед сортировкой, а запятые слева оцениваются после.... операторы списка имеют тенденцию сглатывать ... и затем действуют как простой термин "

  1. В результате присваивания обрабатывается сортировка или это происходит, когда @ary расширяется при печати?
  2. Что он подразумевает под всеми этими "запятыми" вещами? Насколько я понимаю, в операторе присваивания запятая имеет более низкий приоритет, чем оператор списка, поэтому сортировка выполняется первой и поглощает свои аргументы (4 and 2) .. Какчерт возьми, когда вообще вычисляется запятая ?? Так что statemnent становится (1, 3, 2, 4) списком, который назначается .. запятая просто действует как разделитель списка, а не как оператор !! На самом деле на pg:108 он говорит: не путайте использование скалярного контекста через запятую с использованием контекста списка ..
  3. Что такое левый и правый оператор списка? print @ary является правым оператором списка ??очень низкий приоритет?

    print ($ foo, exit);

здесь, как оценивается приоритет? print - оператор списка, который выглядит как функция, поэтому долженбеги первым! яУ t есть два аргумента $foo и exit .. так почему выход не обрабатывается как строка ???После того, как вся приоритетная печать (оператор списка) имеет более высокий приоритет ??

print $foo, exit;

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

   print ($foo & 255) + 1, "\n";

здесь, так как это оператор списка, он печатает $foo & 255 Если что-то подобное не произойдет с вышеупомянутым exit материалом ..

Ответы [ 3 ]

3 голосов
/ 17 февраля 2011

Если вы сомневаетесь в том, как Perl анализирует конструкцию, вы можете запустить код через модуль B::Deparse, который сгенерирует исходный код Perl из скомпилированного внутреннего представления. Для вашего первого примера:

$ perl -MO=Deparse,-p -e '@ary = (1, 3, sort 4, 2); print @ary;'
(@ary = (1, 3, sort(4, 2)));
print(@ary);
-e syntax OK

Итак, как вы можете видеть, sort принимает два аргумента справа.

Что касается порядка выполнения, вы можете узнать это с помощью модуля B::Concise (я добавил комментарии):

$ perl -MO=Concise,-exec -e '@ary = (1, 3, sort 4, 2); print @ary;'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s       # start of list
4  <$> const[IV 1] s    # 1 is added to list
5  <$> const[IV 3] s    # 3 is added to list
6  <0> pushmark s       # start of sort's argument list
7  <$> const[IV 4] s    # 4 is added to sort's argument list
8  <$> const[IV 2] s    # 2 is added to sort's argument list
9  <@> sort lK          # sort is run, and returns its list into the outer list
a  <0> pushmark s
b  <#> gv[*ary] s
c  <1> rv2av[t2] lKRM*/1
d  <2> aassign[t3] vKS/COMMON  # the list is assigned to the array
e  <;> nextstate(main 1 -e:1) v:{
f  <0> pushmark s         # start of print's argument list
g  <#> gv[*ary] s         # the array is loaded into print's argument list
h  <1> rv2av[t5] lK/1
i  <@> print vK           # print outputs it's argument list
j  <@> leave[1 ref] vKP/REFC
-e syntax OK

Для вашего второго примера:

$ perl -MO=Deparse,-p -e 'print $foo, exit;'
print($foo, exit);
-e syntax OK

$ perl -MO=Concise,-exec -e 'print $foo, exit;'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark s
4  <#> gvsv[*foo] s   # add $foo to the argument list
5  <0> exit s         # call `exit` and add its return value to the list
6  <@> print vK       # print the list, but we never get here
7  <@> leave[1 ref] vKP/REFC
-e syntax OK

Итак, как вы можете видеть, встроенная функция exit запускается при попытке собрать список аргументов для print. Поскольку exit приводит к закрытию программы, команда print никогда не запускается.

И последний:

$ perl -MO=Deparse,-p -e 'print ($foo & 255) + 1, "\n";'
((print(($foo & 255)) + 1), '???');  # '???' means this was optimized away
-e syntax OK

$ perl -MO=Concise,-exec -e 'print ($foo & 255) + 1, "\n";'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <0> pushmark v
4  <0> pushmark s
5  <#> gvsv[*foo] s
6  <$> const[IV 255] s
7  <2> bit_and[t2] sK
8  <@> print sK
9  <$> const[IV 1] s
a  <2> add[t3] vK/2
b  <@> list vK
c  <@> leave[1 ref] vKP/REFC
-e syntax OK
3 голосов
/ 17 февраля 2011
  1. sort оценивается при вызове, это действительно не имеет никакого отношения к назначению.sort возвращает список.Итак, вы присваиваете:

    @ ary = (1, 3, (2,4));

Perl игнорирует вторую скобку, так что вы в конечном итогес 1,3,2,4, как и следовало ожидать.

  1. Запятая, на которую вы ссылаетесь, больше не существует.Это второй аргумент для сортировки.Perl видит ваш список как список из 3 элементов, а не как список из 4 элементов (в назначении он расширяется до 4)

  2. вправо что-то делает с параметрами (например, печатает их или сохраняет их)), leftward делает что-то для параметров, обычно изменяя их каким-либо образом.

print действует как любая другая функция в Perl (или любом другом языке, который я когда-либо использовал для этогоиметь значение).Если вы вызываете функцию в качестве аргумента, возвращаемое значение этой функции дается в качестве аргумента.Так что ваш случай:

print ($foo, exit);

или эквивалентный (парены не имеют значения)

print $foo, exit;

ничего не делает, потому что вы просите его напечатать возвращаемое значение exit.Ваша программа выходит первой, поэтому вы ничего не получаете обратно.Я не понимаю, почему вы ожидаете, что exit будет рассматриваться как строка.exit - это функция во всех контекстах, если вы не процитировали ее.

print ($foo & 255) + 1,"\n";

С perlop, которая приводит этот пример:

, вероятно, не выполняет то, что вы ожидаете вПервый взгляд.Скобки заключают список аргументов для «print», который оценивается (вывод результата «$ foo & 255»).Затем один добавляется к возвращаемому значению «print» (обычно 1).Результат примерно такой:

1 + 1, "\n";    # Obviously not what you meant.

Чтобы сделать то, что вы имели в виду, вы должны написать:

print(($foo & 255) + 1, "\n");
0 голосов
/ 18 февраля 2011

Не уверен, что то, что следует, совершенно точно (это путаница от IRC, вышеупомянутые ответы, Google и моя интерпретация книги)

  1. (оператор) (операнды) это рассматривается как левый оператор, потому что это слева от операндов. (операнды) (оператор) это рассматривается как правый оператор, потому что это справа от операндов. Итак, (1, 2, 3, сортировка 4, 5, сортировка 6, 7) Здесь второй сорт действует как оператор левого и правого слова !! Сортировка 6,7 является левым словом, как слева от (6,7) - это операнды. Это также справа от сортировки (4, 5, так что здесь это направо и имеет очень низкий приоритет.

@ ary = (1, 3, сорт 4, 2); print @ary;

здесь, sort - это левый оператор списка, поэтому его приоритет самый высокий и, как говорит 'Cfreak' ..

  1. print ($ foo, выход); выведите $ foo, выход;

Здесь print - это левый список, поэтому он имеет самый высокий приоритет и поэтому должен выполняться первым, НО! чтобы выполнить его, нужно разрешить его аргументы и голое слово «выход». Чтобы решить эту проблему, я полагаю, что она запускает команду exit, ergo .. Print $ foo, ... сожрет все свои аргументы, затем обработает их и, используя голое слово, запустит ..

  1. print ($ foo & 255) такой же, как указано выше. print получает наивысший приоритет, но теперь ему нужно разрешить различные аргументы ... так что $ foo & 255 и т. д., как объяснил 'Cfreak'.

Большое спасибо, ребята!

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