Может ли кто-нибудь объяснить, почему он обращается к последнему элементу в Perl 6
@array[*-1]
и почему нам нужна звездочка *
?
Не логичнее ли делать что-то вроде этого:
@array[-1]
Может ли кто-нибудь объяснить, почему он обращается к последнему элементу в Perl 6
@array[*-1]
и почему нам нужна звездочка *
?
Не логичнее ли делать что-то вроде этого:
@array[-1]
Документация пользователя объясняет, что *-1
- это всего лишь объект кода, который также может быть записан как
-> $n { $n - 1 }
При передаче в [ ]
он будет вызываться с размером массива в качестве аргумента для вычисления индекса.
Таким образом, вместо того, чтобы просто начать отсчет назад от конца массива, вы можете использовать его, например, для того, чтобы рассчитывать вперед из своего центра с помощью
@array[* div 2] #=> middlemost element
@array[* div 2 + 1] #=> next element after the middlemost one
В соответствии с проектными документами причина запрета отрицательных индексов (которые могли быть приняты даже при вышеуказанном обобщении) заключается в следующем:
Семантика Perl 6 позволяет избежать индексирования разрывов (источник тонких ошибок времени выполнения) и обеспечивает порядковый доступ в обоих направлениях на обоих концах массива.
Если вам не нравится какая-либо звезда, вы также можете:
my $last-elem = @array.tail;
или даже
my ($second-last, $last) = @array.tail(2);
Изменить: Конечно, существует также метод head
:
my ($first, $second) = @array.head(2);
Другие два ответы превосходны. Моя единственная причина для ответа заключалась в том, чтобы добавить немного больше объяснений о синтаксисе индексирования Whatever Star *
.
Эквивалент синтаксиса Perl 6 @array[*-1]
в Perl 5 будет $array[ scalar @array - 1]
. В Perl 5 в скалярном контексте массив возвращает количество элементов, которые он содержит, поэтому scalar @array
дает длину массива. Вычитание одного из них дает вам последний индекс массива.
Так как в Perl 6 индексы могут быть ограничены, чтобы никогда не быть отрицательными, если они отрицательны, то они определенно выходят за допустимые пределы. Но в Perl 5 отрицательный индекс может быть или не быть "вне диапазона". Если он выходит за пределы допустимого диапазона, тогда он дает только значение undefined, которое нелегко отличить от простого значения undefined в элементе.
Например, код Perl 5:
use v5.10;
use strict;
use warnings;
my @array = ('a', undef, 'c');
say $array[-1]; # 'c'
say $array[-2]; # undefined
say $array[-3]; # 'a'
say $array[-4]; # out of range
say "======= FINISHED =======";
приводит к двум почти одинаковым предупреждениям, но все еще заканчивается:
c
Use of uninitialized value $array[-2] in say at array.pl line 7.
a
Use of uninitialized value in say at array.pl line 9.
======= FINISHED =======
Но код Perl 6
use v6;
my @array = 'a', Any, 'c';
put @array[*-1]; # evaluated as @array[2] or 'c'
put @array[*-2]; # evaluated as @array[1] or Any (i.e. undefined)
put @array[*-3]; # evaluated as @array[0] or 'a'
put @array[*-4]; # evaluated as @array[-1], which is a syntax error
put "======= FINISHED =======";
также будет предупреждать о используемом значении undefined, но он не работает при использовании индекса, который выходит меньше 0:
c
Use of uninitialized value @array of type Any in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
in block <unit> at array.p6 line 5
a
Effective index out of range. Is: -1, should be in 0..Inf
in block <unit> at array.p6 line 7
Actually thrown at:
in block <unit> at array.p6 line 7
Таким образом, ваш код Perl 6 может быть более надежным, если не дать отрицательных индексов, но вы все равно можете индексировать его с конца, используя синтаксис Whatever Star.
Если вам нужны только последние несколько элементов массива, я бы рекомендовал использовать метод tail
, упомянутый в mscha answer. @array.tail(3)
гораздо более понятен, чем @array[*-3 .. *-1]
.