切片索引的惰性如何影响数组/列表的切片? [RAKU]

问题描述

当我们对索引超出数组边界的数组进行切片时,得到的结果是未定义的(任何)

当我们通过与延迟列表相同的切片索引时,得到的结果是数组/列表的现有值(仅此而已):

my @a = ^5;

say @a[^10];        # (0 1 2 3 4 (Any) (Any) (Any) (Any) (Any))
say @a[lazy ^10];   # (0 1 2 3 4)

很明显,切片索引的惰性会影响结果。

试图弄清事物的方式,并作为概念证明,我编写了切片机制的简单版本:

my @a = ^5;

my @s1 = ^10;
my @s2 = lazy ^10;

sub postcircumfix:<-[ ]-> (@container,@index) {
    my $iter = @index.iterator;

    gather {
        loop {
            my $item := $iter.pull-one;

            if $item =:= IterationEnd {
                last;
            }

            with @container[$item] {
                take @container[$item]
            } else {
                @index.is-lazy ?? { last } !! take @container[$item];
            }
        }
    }
}

say @a-[@s1]-;   # (0 1 2 3 4 (Any) (Any) (Any) (Any) (Any))
say @a-[@s2]-;   # (0 1 2 3 4)

但是我想知道我的天真算法是否描述了事物在幕后的计算方式!

解决方法

在幕后进行工作的来源可以在array_slice.pm6中找到。

具体地说,您可以在L73看到以下内容:

    if is-pos-lazy {
        # With lazy indices,we truncate at the first one that fails to exists.
        my \rest-seq = Seq.new(pos-iter).flatmap: -> Int() $i {
            nqp::unless(
              $eagerize($i),last,$i
            )
        };
        my \todo := nqp::create(List::Reifier);
        nqp::bindattr(todo,List::Reifier,'$!reified',eager-indices);
        nqp::bindattr(todo,'$!current-iter',rest-seq.iterator);
        nqp::bindattr(todo,'$!reification-target',eager-indices);
        nqp::bindattr(pos-list,List,'$!todo',todo);
    }
    else {
        pos-iter.push-all: target;
    }

因此,正如您所猜测的,它确实在列表项不存在之后停止。毫无疑问,这是因为许多惰性列表是无限的,并且迭代器无法提供一种方法来知道它们是否是无限的(生成器可能是不确定的)。

例如,如果您确实想启用这样的功能,则可以编写自己的切片器来处理元素可能不可用的惰性列表,但是您必须注意确保仅在以下情况下才对它们进行热切评估:你知道他们是有限的:

multi sub postcircumfix:<-[ ]-> (@a,@b) {
  lazy gather {
    take @a[$_] for @b;
  }
}

my @a = ^5;
my @b = lazy gather { 
  for ^10 -> $i { 
    # So we can track when elements are evaluated
    say "Generated \@b[$i]"; 
    take $i;
  } 
};

say "Are we lazy? ",@a-[@b]-;
say "Let's get eager: ",@a-[@b]-.eager;
say "Going beyond indices: ",@a-[@b]-[11]

此输出为

Are we lazy? (...)
Generated @b[0]
Generated @b[1]
Generated @b[2]
Generated @b[3]
Generated @b[4]
Generated @b[5]
Generated @b[6]
Generated @b[7]
Generated @b[8]
Generated @b[9]
Let's get eager: (0 1 2 3 4 (Any) (Any) (Any) (Any) (Any))
Going beyond indices: Nil

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...