【问题标题】:Accessing the last element in Perl6访问 Perl6 中的最后一个元素
【发布时间】:2017-01-28 20:27:39
【问题描述】:

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

@array[*-1]  

为什么我们需要星号*

这样做不是更合乎逻辑吗:

@array[-1] 

【问题讨论】:

    标签: raku


    【解决方案1】:

    user documentation 说明*-1 只是一个代码对象,也可以写成

    -> $n { $n - 1 }
    

    当传递给[ ] 时,它将以数组大小作为参数调用以计算索引。

    因此,您不仅可以从数组的末尾开始倒数,还可以使用它来例如从其中心通过

    @array[* div 2]     #=> middlemost element
    @array[* div 2 + 1] #=> next element after the middlemost one
    

    根据design documents,取缔负指数的原因(即使有了上述概括也可以接受)是这样的:

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

    【讨论】:

      【解决方案2】:

      如果你不喜欢whatever-star,你也可以这样做:

      my $last-elem = @array.tail;
      

      甚至

      my ($second-last, $last) = @array.tail(2);
      

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

      my ($first, $second) = @array.head(2);
      

      【讨论】:

        【解决方案3】:

        其他two answers 都很棒。我回答的唯一原因是添加更多关于 What Star * 数组索引语法的解释。

        Perl 5 中 Perl 6 的 @array[*-1] 语法等效为 $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 =======";
        

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

        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 =======";
        

        同样会警告正在使用的未定义值,但在使用小于 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 代码可以更加健壮,但是您仍然可以使用 What Star 语法从末尾开始索引。

        最后的忠告

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-02-19
          • 1970-01-01
          • 1970-01-01
          • 2015-09-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-10
          相关资源
          最近更新 更多