当前位置:  开发笔记 > 编程语言 > 正文

如何在Perl 6中使用非缓存无限延迟列表

如何解决《如何在Perl6中使用非缓存无限延迟列表》经验,为你挑选了2个好方法。

无限懒惰列表真棒!

> my @fibo = 0, 1, *+* ... *;
> say @fibo[1000];
43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875

它们会自动缓存它们的值,这在大多数情况下都很方便.但是当使用巨大的Fibonacci数字(例子)时,这可能会导致内存问题.

不幸的是,我无法弄清楚如何创建非缓存Fibonacci序列.任何人?



1> Brad Gilbert..:

一个主要问题是你将它存储在一个数组中,这当然保留了它的所有值.

接下来的问题有点微妙,dotty序列生成器语法LISTCODE ... END不知道该CODE部件要求的先前值有多少,因此它保留了所有这些值.
(它可以看看它的arity/count CODE,但目前似乎不是来自REPL的实验)

然后有一个问题就是&postcircumfix:<[ ]>在Seq上调用.cache假设你要在某个时候要求另一个值.
(从查看Seq.AT-POS的来源)

未来的实施可能会更好地解决这些缺点.


您可以使用不同的功能创建序列,以克服dotty序列生成器语法的当前限制.

sub fibonacci-seq (){
  gather {
    take my $a = 0;
    take my $b = 1;

    loop {
      take my $c = $a + $b;
      $a = $b;
      $b = $c;
    }
  }.lazy
}

如果您只是迭代值,您可以按原样使用它.

my $v;
for fibonacci-seq() {
  if $_ > 1000 {
    $v = $_;
    last;
  }
}
say $v;

my $count = 100000;
for fibonacci-seq() {
  if $count-- <= 0 {
    $v = $_;
    last;
  }
}
say chars $v; # 20899

您也可以直接使用Iterator.虽然在大多数情况下这不是必需的.

sub fibonacci ( UInt $n ) {
  # have to get a new iterator each time this is called
  my \iterator = fibonacci-seq().iterator;
  for ^$n {
    return Nil if iterator.pull-one =:= IterationEnd;
  }
  my \result = iterator.pull-one;
  result =:= IterationEnd ?? Nil !! result
}

如果您有最新版本的Rakudo,您可以使用skip-at-least-pull-one.

sub fibonacci ( UInt $n ) {
  # have to get a new iterator each time this is called
  my \result = fibonacci-seq().iterator.skip-at-least-pull-one($n);
  result =:= IterationEnd ?? Nil !! result
}

您也可以直接实现Iterator类,将其包装在Seq中.
(这主要是如何在Rakudo核心中编写返回序列的方法)

sub fibonacci-seq2 () {
  Seq.new:

  class :: does Iterator {

    has Int $!a = 0;
    has Int $!b = 1;

    method pull-one {
      my $current = $!a;
      my $c = $!a + $!b;
      $!a = $!b;
      $!b = $c;
      $current;
    }

    # indicate that this should never be eagerly iterated
    # which is recommended on infinite generators
    method is-lazy ( --> True ) {}

  }.new
}



 ... 

(我是对的,如果规则只是你使用了`@` sigil或明确地称为`.cache`你只有缓存,那么这个问题的答案将是对我的$ fibo的微不足道的优雅改变= 0,1,*+*...*;说$ fibo [1000];`?)

2> Elizabeth Ma..:

显然,一个菜鸟无法发表评论.

在定义一个惰性迭代器(例如sub fibonacci-seq2)时,应该通过添加返回True的"is-lazy"方法将迭代器标记为延迟,例如:

method is-lazy(--> True) { }

这将允许系统更好地检测可能的infiniloops.

推荐阅读
周扒pi
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有