关于懒惰[RAKU] [英] About Laziness [ RAKU ]

查看:61
本文介绍了关于懒惰[RAKU]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Raku文档中指出,正在对聚集结构进行惰性评估.在以下示例中,我很难得出关于结构的惰性的结论:

 说迭代到无穷大是:",(1 ... Inf).说收集者是:",收集{取0;我的($ last,$ this)= 0,1;环形 {拿$ this;($ last,$ this)= $ this,$ last + $ this;}}.什么;说 ' -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - ';我的@ f1 =懒人聚集{取0;我的($ last,$ this)= 0,1;环形 {拿$ this;($ last,$ this)= $ this,$ last + $ this;}}说'@ f1:',@ f1.说'@ f1 is lazy:',@ f1.is-lazy;说 ' -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  - ';我的@ f2 = 1 ... Inf;说'@ f2:',@ f2.说'@ f2 is lazy:',@ f2.is-lazy; 

在第一种情况下(将Seq分配给@ f1),如果我们取消了惰性"定义,则生成的Sequence(使用collect-take)将永远运行(不惰性).

在第二种情况下(将Seq分配给@ f2)@ f2变得很懒.

为什么我们在行为上有差异?尽管我们尝试做同样的事情:以惰性方式将Seq分配给数组

有人可以澄清这个问题吗?

解决方案

Raku文档中指出,正在偷懒评估收集结构.

可以可以.但不一定.他们很高兴以任何一种方式工作.

在按键扭曲中,如果聚集请求(如果它是惰性的),它将返回 False .这就是导致您看到的行为的原因.

采取#1: gather 表现懒惰

的一种方式

gather 在需要时评估其顺序中的下一个元素.这是懒惰评估的经典定义,如Wikipedia所述:

惰性评估...延迟对表达式的评估,直到需要其值为止

采取#2: gather 表现懒惰

的第二种方式

一些使用值序列的构造总是懒惰地使用它们.如果他们使用的序列是 gather ,则他们会懒惰地要求其值.在这种情况下, gather 会强制执行,评估其顺序,直到达到 take ,然后

In the second case (assignement of a Seq to @f2) @f2 becomes lazy.

Why do we have a differentiation in behaviour? although we try to do the same thing: Assign a Seq to an array in a lazy way

Can someone clarify the matter ???

解决方案

In Raku documentation it is stated that gather-take constructs are being lazy evaluated.

They can be. But not necessarily. They're perfectly happy to work either way.

In a key twist, if a gather is asked if it's lazy, it returns False. This is what results in the behaviour you see.

Take #1: One way gather behaves lazily

gather evaluates the next element in its sequence when it's needed. This is the classic definition of lazy evaluation, as described by Wikipedia:

lazy evaluation ... delays the evaluation of an expression until its value is needed

Take #2: A second way gather behaves lazily

Some constructs that consume sequences of values always consume them lazily. If the sequence they're consuming is a gather, they demand its values lazily. In which case the gather obliges, evaluating its sequence until it reaches a take, and then yielding until the next value is demanded.

Take #3: One way gather behaves eagerly

Some constructs that consume sequences of values always consume them eagerly. If a sequence they're consuming is a gather, they demand its values eagerly. In which case the gather obliges, and any laziness in it is moot.

Take #4: A second way gather behaves eagerly

Some constructs that consume sequences of values demand them either lazily or eagerly, based on the sequence's answer to an .is-lazy call on it; if it returns True, then its values are demanded lazily, otherwise they're demanded eagerly.

And here comes a critical twist: when .is-lazy is called on a gather construct, it returns False.

Take #5: What's happening in your examples

say .is-lazy
for (gather { take 42 }),                 # False
    (gather { loop { take 42 } });        # False

In your @f1 = gather ... case, @f1 is being assigned a sequence that says it's not lazy. This is so even though it contains an infinite loop. @ sigil'd variables take that as a cue to eagerly assign the sequence -- and the code hangs.


The prefix lazy creates a new Seq that lazily draws from the expression on its right. It also returns True if .is-lazy is called on it:

say .is-lazy
for (lazy gather { take 42 }),            # True
    (lazy gather { loop { take 42 } });   # True

If an @ sigil'd variable is assigned a value that returns True for a call to .is-lazy, the assignment, and the variable, are lazy. So the code @f1 = lazy gather ... works fine.


Finally, the sequence (1...Inf) knows it's lazy, and tells the world it is, without needing a prefix lazy:

say .is-lazy with (1 ... Inf)             # True

So assigning that also works fine, with or without lazy.


In summary, an @ sigil'd variable gains elements lazily if a Seq assigned to it says it's lazy, and eagerly otherwise.


You didn't ask about this, but another scenario is assigning or binding a Seq to a $ sigil'd variable, or a sigil free identifier.

As with a @ sigil'd variable, calling .is-lazy on the $ sigil'd variable or sigil free identifier will return True or False in accord with the assigned/bound Seq.

But then, regardless of whether that .is-lazy returns True or False, the Seq will still be iterated lazily.

这篇关于关于懒惰[RAKU]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆