Назначение списка в скалярном контексте - PullRequest
12 голосов
/ 16 февраля 2012

Присвоение списка в скалярном контексте возвращает количество элементов с правой стороны:

scalar(my ($hello, $there, $world) = (7,8)); #evaluates to 2

Почему оно оценивает правую часть и выдает 2 вместо вновь определенного списка, который оценивается ивозвращая 3?

Мне кажется, $hello получает 7, $there получает 8, а $world получает undef, тогда этот список оценивается в скалярном контексте, что приведет к 3, так какколичество элементов в списке ($hello $there $world).Мне кажется странным, что контекст влияет на то, какая часть вычисленного выражения возвращается:

my $greeting = (($hello, $there, $world) = (7,8)); #2

my @greeting = (($hello, $there, $world) = (7,8));
my $greeting_length = @greeting; #3

Ответы [ 3 ]

15 голосов
/ 16 февраля 2012

Документально подсчитано количество элементов справа в perlop (последнее предложение в разделе «Операторы присваивания»):

Аналогично, назначение списка в контексте списка создаетсписок назначенных значений l и присвоение списка в скалярном контексте возвращает число элементов, созданных выражением в правой части назначения.

Причина, по которой он работает подобным образом, заключается в том, что выможно написать что-то вроде этого:

while (my ($key, $value) = each %hash) { ... }

Если бы он посчитал количество элементов в левой части присваивания, это был бы бесконечный цикл.

Если подумать,количество элементов в левой части либо совпадает с количеством в правой части, либо является константой (когда вы назначаете список скаляров).В первом случае не имеет значения, какую сторону вы считаете, а во втором случае подсчет с правой стороны более полезен.

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

Re: ваш комментарий В вашем примере (7,8) - этодвухэлементный список, поэтому оператор присваивания возвращает 2. Когда вы присваиваете более короткий список более длинному списку скаляров, правая часть не «дополняется» до undef до того, как произойдет назначение.Вместо этого любые переменные, которые не имеют значения, связанного с ними из правого списка, сбрасываются до значения по умолчанию.Для скалярной переменной это undef.Для массивов это пустой массив.Для хэшей это пустой хэш.

6 голосов
/ 16 февраля 2012
Мне кажется странным тот эффект контекста, какая сторона оценивается:

Это не так. Оцениваются обе стороны (операнды) оператора назначения списка, и то, оценивается ли назначение списка в скалярном контексте или контексте списка, никак не влияет на оценку операндов.

Оценивается ли присвоение списка в скалярном контексте или контекст списка только на значение, которое оно возвращает.

Ранее я создал Оператор скалярного присваивания списка , который пытается прояснить различия между двумя операторами присваивания и их поведением в скалярном контексте и контексте списка.

0 голосов
/ 09 октября 2018

Почему он оценивает правую часть и выдает 2, вместо того, чтобы вновь определенный список оценивался и возвращал 3?

Потому что именно так и должно определяться определение языка, потому что именно так решил Ларри Уолл.

Мне кажется, что $ hello получает 7, $ туда получает 8, а $ world получает undef, тогда этот список оценивается в скалярном контексте

Нет, Perl не работает таким образом. Вы предполагаете, что скалярный контекст - это просто преобразование результата, который был бы получен в контексте списка, в скаляр путем подсчета количества элементов в результате списка, но это просто неправильно ... скалярный контекст означает, что операция (в этом случае присваивание) должно давать скалярный результат, и часто есть скалярные результаты, которые более полезны, чем просто число элементов в результате контекста списка, и которые варьируются от оператора к оператору ... вы должны проверить документацию за что скаляр производит; это не равномерно. Для назначения списка скалярное значение - это число элементов с правой стороны, потому что это гораздо более полезно, чем число получателей, которое является постоянным. например, if (($a, $b) = $s =~ /$re/) истинно, если совпадение дало результаты, в отличие от того, чтобы всегда быть истиной, потому что есть два получателя.

Мне кажется странным, что контекст влияет на то, какая часть оцениваемого выражение возвращается

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

...