访问Perl6中的最后一个元素

smi*_*ith 14 perl6 raku

有人可以解释为什么这会访问Perl 6中的最后一个元素

@array[*-1]  
Run Code Online (Sandbox Code Playgroud)

为什么我们需要星号*

做这样的事情不是更合乎逻辑:

@array[-1] 
Run Code Online (Sandbox Code Playgroud)

Chr*_*oph 16

用户文档解释说,*-1仅仅是一个代码对象,这也可以写成

-> $n { $n - 1 }
Run Code Online (Sandbox Code Playgroud)

传递给[ ]它时,将使用数组大小​​作为参数调用它来计算索引.

因此,您不仅可以从数组的末尾开始向后计数,而是可以使用它来例如从中心向前计数

@array[* div 2]     #=> middlemost element
@array[* div 2 + 1] #=> next element after the middlemost one
Run Code Online (Sandbox Code Playgroud)

根据设计文件,禁止负指数的原因(即使采用上述推广也可以接受)是这样的:

Perl 6语义避免索引不连续性(微妙的运行时错误的来源),并在数组的两端提供两个方向的顺序访问.


msc*_*cha 12

如果你不喜欢任何明星,你也可以这样做:

my $last-elem = @array.tail;
Run Code Online (Sandbox Code Playgroud)

甚至

my ($second-last, $last) = @array.tail(2);
Run Code Online (Sandbox Code Playgroud)

编辑: 当然,还有一种head方法:

my ($first, $second) = @array.head(2);
Run Code Online (Sandbox Code Playgroud)


Chr*_*oms 7

另外两个 答案非常好.我回答的唯一理由是添加一些关于Whatever Star *数组索引语法的更多解释.

@array[*-1]在Perl 5 中Perl 6的语法相当于$array[ scalar @array - 1].在Perl 5中,在标量上下文中,数组返回它包含的项目数,因此scalar @array为您提供数组的长度.从中减去一个可以得到数组的最后一个索引.

因为在Perl 6中,索引可以被限制为永远不会是负数,如果它们是负数,那么它们肯定会超出范围.但在Perl 5中,负指数可能会或可能不会"超出范围".如果它超出范围,那么它只会给你一个未定义的值,这个值不容易与元素中的未定义值区分开来.

例如,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 =======";
Run Code Online (Sandbox Code Playgroud)

导致两个几乎相同的警告,但仍然完成运行:

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 =======
Run Code Online (Sandbox Code Playgroud)

但是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 =======";
Run Code Online (Sandbox Code Playgroud)

同样会警告使用的未定义值,但是在使用小于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
Run Code Online (Sandbox Code Playgroud)

因此,通过不允许负索引,您的Perl 6代码可以更强大,但您仍然可以使用Whatever Star语法从最终索引.

最后的建议

如果你只需要数组的最后几个元素,我建议使用mscha的答案中tail提到的方法.更加不言自明.@array.tail(3)@array[*-3 .. *-1]