jak*_*kar 7 arrays lazy-evaluation rakudo lazy-sequences raku
在 Raku 文档中指出,gather-take 构造正在被惰性评估。在下面的例子中,我很难对结构的懒惰得出结论:
say 'Iterate to Infinity is : ', (1 ... Inf).WHAT;
say 'gather is : ', gather {
take 0;
my ($last, $this) = 0, 1;
loop {
take $this;
($last, $this) = $this, $last + $this;
}
}.WHAT;
say '------------------------------------';
my @f1 = lazy gather {
take 0;
my ($last, $this) = 0, 1;
loop {
take $this;
($last, $this) = $this, $last + $this;
}
}
say '@f1 : ', @f1.WHAT;
say '@f1 is lazy : ', @f1.is-lazy;
say '------------------------------------';
my @f2 = 1 ... Inf;
say '@f2 : ', @f2.WHAT;
say '@f2 is lazy : ', @f2.is-lazy;
Run Code Online (Sandbox Code Playgroud)
在第一种情况下(将 Seq 分配给@f1),如果我们去掉“懒惰”定义,那么生成的序列(使用gather-take)将永远运行(不是懒惰)。
在第二种情况下(将 Seq 分配给 @f2)@f2 变得懒惰。
为什么我们在行为上有差异?尽管我们尝试做同样的事情:以懒惰的方式将 Seq 分配给数组
有人能澄清一下吗???
在 Raku 文档中指出,gather-take 构造正在被惰性评估。
他们可以。但不一定。他们非常乐意以任何一种方式工作。
关键gather是,如果 a被问到它是否是惰性的,它会返回False。这就是您看到的行为的结果。
gather表现得懒惰gather在需要时评估其序列中的下一个元素。这是懒惰评估的经典定义,如维基百科所述:
惰性求值 ... 延迟表达式的求值,直到需要它的值
gather表现得懒惰一些消耗值序列的构造总是懒惰地消耗它们。如果他们消耗的序列是 a gather,他们就会懒惰地要求它的值。在这种情况下,gather有义务评估其序列直到达到 a take,然后屈服直到要求下一个值。
gather表现得热切一些消耗值序列的构造总是急切地消耗它们。如果他们使用的序列是 a gather,他们会急切地要求它的值。在这种情况下,gather义务和其中的任何懒惰都是没有意义的。
gather表现得热切一些消耗值序列的构造基于序列对其调用的回答,或者懒惰或急切地要求它们.is-lazy;如果它返回True,那么它的值被懒惰地要求,否则他们急切地被要求。
这里有一个关键的转折:在构造.is-lazy上调用时gather,它返回False。
say .is-lazy
for (gather { take 42 }), # False
(gather { loop { take 42 } }); # False
Run Code Online (Sandbox Code Playgroud)
在您的@f1 = gather ...情况下,@f1被分配了一个序列,表示它不是懒惰的。即使它包含无限循环也是如此。@带有标记的变量将其作为急切分配序列的提示——并且代码挂起。
前缀lazy创建了一个新的Seq,它从它右边的表达式中懒惰地绘制。True如果.is-lazy被调用它也会返回:
say .is-lazy
for (lazy gather { take 42 }), # True
(lazy gather { loop { take 42 } }); # True
Run Code Online (Sandbox Code Playgroud)
如果为@sigil'd 变量分配了一个值,该值True在调用 时返回.is-lazy,则赋值和变量都是惰性的。所以代码@f1 = lazy gather ...工作正常。
最后,序列(1...Inf) 知道它是懒惰的,并告诉世界它是懒惰的,不需要前缀lazy:
say .is-lazy with (1 ... Inf) # True
Run Code Online (Sandbox Code Playgroud)
因此,分配也可以正常工作,无论是否有lazy.
总而言之,@如果Seq分配给一个带有符号的变量表示它是惰性的,则它会懒惰地获取元素,否则就会急切地获取元素。
您没有问过这个问题,但另一种情况是将 a 分配或绑定Seq到$sigil'd 变量,或 sigil free 标识符。
作为具有@sigil'd变量,调用.is-lazy在$sigil'd变量或印记自由标识符将返回True或False在与分配的/约束一致Seq。
但是,无论是.is-lazy返回True还是False,Seq仍然会被懒惰地迭代。