Есть ли такая вещь, как список в скалярном контексте?
my $mind = ( 'a', 'little', 'confused' );
И это потому, что perldoc perlfaq4
объясняет строку выше следующим образом (выделение добавлено):
Поскольку вы назначаете скаляр, правая часть находится в скалярном контексте. Оператор запятой (да, это оператор!) В скалярном контексте оценивает его левую часть, отбрасывает результат, оценивает его правую часть и возвращает результат. По сути, этот список-двойник присваивает
$scalar
это самая правая ценность. Многие люди путают это, потому что они выбирают список-двойник, последним элементом которого также является ожидаемое количество:my $scalar = ( 1, 2, 3 ); # $scalar gets 3, accidentally
Я понимаю, что это означает, что в скалярном контексте нет такого понятия, как список.
Тем не менее, ikegami утверждает, что он "приводит [s] к оператору списка, поэтому он является литералом списка".
Так это список или нет?
6 ответов
Литерал списка - это то, что на самом деле представляет собой список, написанный в коде, поэтому (1, 2, 3)
является литералом списка, тогда как caller
например, это функция, которая может возвращать список или скаляр в зависимости от контекста.
В строке, как:
my $x = ...;
...
видит скалярный контекст, так что если ...
если бы вы были литералом списка, то вы бы получили список литералов в скалярном контексте:
my $x = (1, 2, 3);
но литерал списка не приводит к списку, поскольку содержащийся в нем оператор запятой видит скалярный контекст, который затем приводит к тому, что он возвращает последний элемент литерала списка и отбрасывает оставшиеся значения после их оценки.
С точки зрения функции, сама функция видит любой контекст, из которого она вызвана, который затем распространяется на любую строку в этой функции, которая возвращает. Таким образом, вы можете иметь функцию в скалярном, списочном или пустом контексте, и если последняя строка этого подпункта окажется литералом списка, этот литерал списка увидит любой из этих контекстов и будет вести себя соответствующим образом.
Так что в основном это различие терминологии, с list literal
ссылаясь на разделенный запятыми список значений в фактическом исходном коде *, и list
ссылаясь на последовательность значений, помещенных в стек perl.
Вы можете написать подпрограммы с возвращаемыми значениями, которые ведут себя как массивы или как списочные литералы в зависимости от контекста.
sub returns_like_array {my @x = 1..5; return @x}
sub returns_like_list {my @x = 1..5; return @x[0 .. $#x]}
* или что-то, что приводит к списку значений через запятую, например qw()
или толстая запятая =>
или хеш или фрагмент массива.
Вы также можете посмотреть мой ответ здесь: Как я могу получить первый элемент из функции, которая возвращает массив в Perl? который входит в чуть более подробно о списках.
Я согласен с вами и с perlfaq4
, Цитировать perldata
, что, вероятно, является окончательной документацией по этому вопросу:
В контексте, не требующем значения списка, значение того, что кажется литералом списка, является просто значением конечного элемента, как в случае с оператором C запятой.
(акцент мой).
Тем не менее, икегами имеет право использовать любую терминологию, которую он хочет. Разные люди думают о разных языковых конструкциях в разных терминах, и, пока конечные результаты одинаковы, я не думаю, что имеет значение, отличается ли их терминология от терминологии в документации. (Однако не стоит настаивать на своеобразной терминологии на публичном форуме!)
Просто спросите Perl!
>perl -MO=Concise,-exec -e"my $s = ($x, $y, $z);"
1 <0> enter
2 <;> nextstate(main 1 -e:1) v:{
3 <0> pushmark v
4 <#> gvsv[*x] s
5 <#> gvsv[*y] s
6 <#> gvsv[*z] s
7 <@> list sKP <--- list in (s)calar context.
8 <0> padsv[$s:1,2] sRM*/LVINTRO
9 <2> sassign vKS/2
a <@> leave[1 ref] vKP/REFC
Так что да, можно иметь список в скалярном контексте.
Невозможно вернуть список в скалярном контексте. (Ну, это возможно из XS, но программа завершится сбоем, возможно, с ошибкой "Bizarre copy".)
Другого не может быть. Если бы существовал отдельный список операций и запятая, было бы невозможно скомпилировать следующее:
sub f { "a", "b", "c" }
Приведет ли это к списку или запятому? На самом деле такого различия нет, так что да, это приводит к тому, что оп.
Это вопрос терминологии и перспективы. Терминология здесь сложная, потому что вы можете написать список в исходном коде, вернуть список значений или оценить что-либо в контексте списка... и слово "список" означает что-то немного различное в каждом случае!
Технически, список не может существовать в скалярном контексте, потому что perl (интерпретатор) не создает список значений для таких вещей:
my $x = ('a', 'b', 'c');
Будучи педантично точным, это объясняется как поведение оператора запятой в скалярном контексте. Так же, qw
определяется как возвращение последнего элемента в скалярном контексте, поэтому здесь тоже нет списка:
my $x = qw(a b c);
В обоих этих случаях (и для любых других примеров операторов, которые мы могли бы собрать) мы говорим о том, что интерпретатор не создает список значений. Это деталь реализации. Нет причины, по которой perl не мог создать список значений и выбросить все, кроме последнего; он просто не хочет.
Perl язык абстрактный. На уровне исходного кода ('a', 'b', 'c')
это список. Вы можете использовать этот список в выражении, которое налагает на него скалярный контекст, поэтому с этой точки зрения список может существовать в скалярном контексте.
В конце концов, это выбор между ментальными моделями того, как работает [Pp]erl. Модель "Список в скалярном контексте возвращает свое последнее значение" немного неточна, но ее проще понять. Насколько я знаю, нет никаких угловых случаев, когда это функционально некорректно. Модель "Нет такого понятия, как список в скалярном контексте" является более точной, но с ней сложнее работать, так как необходимо учитывать поведение каждого оператора в скалярном контексте.
Это не список. Поскольку вы присваиваете скаляр, это оператор запятой - вычисляет левую сторону, вычисляет правую сторону, возвращает правую сторону и разрешает слева направо. $scalar
будет 'confused'
:)