01:00

----
@a1 = ('one','two','three');
$b1 = @a1;
$a2 = ('one','two','three');

print @a1."\n";
print $b1."\n";
print $a2."\n";
-------
Такой код выводит

3
3
three

Значение "3" выводится потому, что массив интерпретируется в скалярном контексте и в этом контексте возвращается число элементов массива.
Вопрос: почему выводится three? Ведь ('one','two','three') - список, который должен быть интерпретирован в скалярном контексте, следовательно я ожидал от него 3.

Вот здесь можно потестить: codepad.org/NIkJL6qW

@темы: Perl

Комментарии
04.11.2010 в 04:02

Люди никогда не достигнут совершенства, пока будут оставаться людьми...
В данном случае, вы немного не поняли мануала. Контекст определяется, как бы так сказать, слева направо.
Т.Е.

@a1 = (1, 2, 3, 4); -- означает, что @a1 -- список, значит будем работать в списточном контексте. После чего интерпретатор, ЗНАЯ контекст, разбирает выражение в скобках.

далее, $b1 = @a1; -- $b1 --- скалярная переменная, значит то, что справа будет интерпретироваться как скаляр, там стоит список, который в скалярном контексте обозначает количество элементов.

далее $a2 = (1, 2, 3); здесь же изначально контекст СКАЛЯРНЫЙ, а значит, скобки задают ПРИОРИТЕТ операций. Сначала выполняется то, что справа, получаем выполнение операции ЗАПЯТАЯ, которая выдаёт свой правый аргумент, после чего идёт присваивание. Всё более чем просто.

Если бы всё было, как хотите Вы, то как отличить, скобку приоритета операций от списка, с учётом того, что есть операция запятая?
Например $a = (2*3 + (4, 8)); как то так. У Perl'а и так убиственный синтаксический анализатор))
04.11.2010 в 04:16

Пау-чок
Открывающая и закрывающая скобки являются ни чем иным, как оператором группировки. Т.е. они в перле не являются аналогом ява- или экшнскриптовским [] или пхпшному array(). Запятая же является оператором перечисления, и имеет менее высокий приоритет, нежели чем присваивание. Встречая запятую в скалярном контексте перл вычисляет все разделённые запятой выражения и возвращает значение последнего из них. В контексте списка она разделяет, собственно, элементы списка.

Приведу примеры:
Выражение

перл вычисляет следующим образом: вычисляется выражение 'one' (которое возвращает строку 'one'), отбрасывает его; затем 'two'(возвращает строку 'two'), снова отбрасывает; затем 'three', и после этого присваивает 'three' переменной $a2.
Если же скобки опустить, написав

Получится то же самое, что:

Т.е. сначала переменной $a2 присвоится 'one', затем вычислится 'two', отбрасывается, затем вычисляется 'three', и результатом полученного выражения будет 'three', которое ничему не присваивается, а значит будет отброшено.

Для понимания разницы интерпретации запятой и идентичности значения скобок полезно также сравнить выражения

и


В первом случае получим массив из трёх элементов, во втором - из одного 'one'. Потому что

эквивалентно

т.к., опять же, запятая имеет меньший приоритет, нежели присваивание.

P.s.. Надеюсь, написал хоть немного понятно. Просто уже совсем спать клонит, мысли связываются с трудом =)
04.11.2010 в 21:03

Всё здорово и понятно! :)

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

Пойду разбираться с анонимными массивами, то бишь которые задаются [].