在Perl 6中,有限列表可以是懒惰的吗?

时间:2017-04-13 08:18:17

标签: lazy-evaluation perl6

假设我有一个序列,我知道起点和终点,发生器很简单。我可以把它变得懒惰吗?

my @b = 0 ... 3;
say 'Is @b lazy? ' ~ @b.is-lazy; # Not lazy

我想将已知列表与自身组合未知次数但不立即生成整个列表。我希望@cross懒惰:

my @cross = [X] @b xx $n;

我知道我可以通过其他简单的事情或编程来做到这一点(而我的Perl 5 Set::CrossProduct就是这样做的),但我很好奇是否有一些我想念的简单而有意的方式。某种方式不会让我依靠自己。

作为一个侧面问题,序列的特征是什么使它变得懒惰?它只是端点吗?如果生成器可以在两者之间产生无限值,是否存在具有已知端点的序列仍然可以是惰性的?我想知道我需要删除多少信息并尝试这样的事情:

my $m = @*ARGS[0];
my @b = 0, * + $m ... ^ * > 3;
say 'Is @b lazy? ' ~ @b.is-lazy;
say '@b: ' ~ @b;

不过,这并不是懒惰。

4 个答案:

答案 0 :(得分:5)

是的,您可以使用lazy method

> my @b = (0 ... 3).lazy;
[...]
> say 'Is @b lazy? ' ~ @b.is-lazy;
Is @b lazy? True

没有什么特别的Seq让它变得懒惰,只是它的基础Iterator

答案 1 :(得分:5)

在我看来,“懒惰”的方法实际上是用词不当。正如cuonglm指出的那样,它唯一说的就是传递底层迭代器声称是懒惰的。但并不意味着什么,真的。迭代器可以在技术上按需生成值,但仍然声称它不是懒惰的。反之亦然。

“is-lazy”检查在内部用于防止需要提前知道元素数量的情况(如.roll或.pick):如果Seq / iterator声称是懒惰的,它将不会实际上尝试,但失败或投掷。

.lazy唯一能做的就是将Seq的迭代器包装到声称是懒惰的另一个迭代器中(如果给定的迭代器声称它不是懒惰的,当然)。除非确实需要,否则请确保它不会提取任何值。因此,添加.lazy并不会告诉我们何时会生成值,只有当它们将被传递时。它有助于测试基于迭代器的逻辑,看看它们如何与声称懒惰的迭代器一起工作。

所以,回到这个问题:如果你想确定某些东西是懒惰的,你将不得不自己编写迭代器。话虽如此,在过去的几个月里,我花费了大量精力在核心中尽可能地使事情变得懒惰。值得注意的是xx N仍然不是懒惰的,尽管它现在确实产生了Seq。让它变得懒惰打破了一些深层次的测试,我还没有弄清楚。展望未来,我认为你可以肯定事情会像通常一样有意义,也许有可能表明有利于内存而不是CPU。但是你永远无法完全控制内置:如果你想要完全控制,你必须自己编写它。

答案 2 :(得分:1)

正如已经指出的那样,is-lazy并不意味着什么。

但我只是想提一下,page on rakudo wiki提供了一些关于is-lazy所期望的线索。

答案 3 :(得分:1)

你可以:

my @b = 0 ... 3;

懒惰只是在正确的位置添加lazy关键字,如下所示:

my @b = lazy 0 ... 3;

或者,正如 cuonglm 指出的那样,您可以调用范围的方法,如下所示:

my @b = (0 ... 3).lazy;