Разница между массивами и списками, а также между списком и скалярным контекстом обсуждалась в сообществе Perl совсем немного в прошлом году (и каждый год, действительно). Я прочитал статьи из chromatic и friedo, а также этот рекомендуется монахам node. Я сейчас пытаюсь понять оператора козла, задокументированного в perlsecret.
Вот какой код я использовал для изучения:
# right side gets scalar context, so commas return rightmost item
$string = qw(stuff junk things);
say $string; # things
# right side gets list context, so middle is list assigned in scalar context
$string = () = qw(stuff junk things);
say $string; # 3
# right side gets list context, so creates a list, assigns an item to $string2, and
# evaluates list in scalar context to assign to $string
$string = ($string2) = qw(stuff junk things);
say $string; # 3
say $string2; # stuff
Я думаю, что я достаточно далеко, чтобы понять всю работу списка и скалярного контекста. Оператор запятой в скалярном контексте возвращает свою правую сторону, поэтому первый пример просто присваивает последнему элементу в выражении запятой (без каких-либо запятых) значение $string
. В других примерах назначение выражения для запятой в список помещает его в контекст списка, поэтому создается список, а списки, оцененные в скалярном контексте, возвращают свой размер.
Есть две части, которые я не понимаю.
Во-первых, списки должны быть неизменными. Это подчеркивается неоднократно friedo. Я полагаю, что назначение через =
из списка в список распределяет назначения из элементов в одном списке на элементы в другом списке, поэтому во втором примере $string2
получает 'stuff'
и почему мы можем распаковать @_
через список. Однако я не понимаю, как возможно работать с ()
, пустым списком. С учетом моего нынешнего понимания, поскольку списки являются неизменными, размер списка останется 0, а затем присвоение размера $stuff
в примерах 2 и 3 даст ему значение 0. Листинги не являются фактически неизменяемыми?
Во-вторых, я читал много раз, что списки фактически не существуют в скалярном контексте. Но объяснение оператора goatse заключается в том, что это назначение списка в скалярном контексте. Не является ли это контр-примером для оператора, который не существует в скалярном контексте? Или что-то еще происходит здесь?
Обновление. Поняв ответ, я думаю, что дополнительная пара круглых скобок помогает концептуализировать, как это работает:
$string = ( () = qw(stuff junk things) );
Внутри parens =
- это присвоение "агрегату", а также оператор присваивания списка (который отличается от оператора скалярного присваивания и который не следует путать с "контекстом списка"; и скалярное присваивание может происходить в любом списке или скалярном контексте). ()
никоим образом не изменяется. =
имеет возвращаемое значение в Perl, а результат назначения списка присваивается $string
через левый =
. Присвоение $string
дает скалярный контекст для RHS (все в parens), а в скалярном контексте возвращаемое значение оператора назначения списка - это количество элементов в RHS.
Вместо этого вы можете назначить назначение списка RHS в контекст списка:
($string) = ( () = qw(stuff junk things) );
В соответствии с perlop назначение списка в контексте списка возвращает список назначенных lvalues, который здесь пуст, поскольку ничего не назначено до ()
. Итак, здесь $string будет undef
.