关于懒惰 [ RAKU ]
About Laziness [ RAKU ]
在 Raku 文档中指出,收集-获取结构正在被惰性评估。在以下示例中,我很难得出关于构造的惰性的结论:
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;
在第一种情况下(将 Seq 分配给@f1)如果我们去掉 "lazy" 定义,那么生成的序列(使用 gather-take)永远是 运行(不是懒)。
在第二种情况下(将 Seq 分配给@f2)@f2 变得懒惰。
为什么我们的行为会有所不同?尽管我们尝试做同样的事情:以惰性方式将 Seq 分配给数组
有人可以澄清一下吗???
In Raku documentation it is stated that gather-take constructs are being lazy evaluated.
他们可以。但不一定。无论哪种方式,他们都非常乐意工作。
在一个关键的转折中,如果 gather
询问 是否懒惰,它 return 就会 False
。这就是导致您看到的行为的原因。
采取 #1:一种方式 gather
表现得 懒惰
gather
在需要时计算其序列中的下一个元素。这是 the classic definition of lazy evaluation, as described by Wikipedia:
lazy evaluation ... delays the evaluation of an expression until its value is needed
采取 #2:第二种方式 gather
表现得 懒惰
一些使用值序列的构造总是延迟使用它们。如果他们消费的序列是 gather
,他们会懒惰地要求它的值。在这种情况下 gather
有义务,评估其序列直到它达到 take
,然后 yielding 直到需要下一个值。
采取 #3:一种方式 gather
表现得 急切
一些消耗值序列的构造总是急切地消耗它们。如果他们正在消费的序列是 gather
,他们会急切地要求它的值。在这种情况下,gather
有义务,任何懒惰都是没有意义的。
采取#4:第二种方式gather
表现急切
一些使用值序列的构造根据序列对 .is-lazy
呼唤它;如果它 returns True
,那么它的值是惰性要求的,否则它们是急切要求的。
这里出现了一个关键的转折:当在 gather
构造上调用 .is-lazy
时,它 returns False
.
练习 #5:您的示例中发生了什么
say .is-lazy
for (gather { take 42 }), # False
(gather { loop { take 42 } }); # False
在您的 @f1 = gather ...
案例中,@f1
被分配了一个表明它 不是 惰性的序列。即使它包含无限循环也是如此。 @
sigil'd 变量将其视为 急切地 分配序列的提示 - 代码挂起。
前缀 lazy
创建了一个新的 Seq
,它懒惰地从其右侧的表达式中提取。它还 returns True
如果 .is-lazy
被调用:
say .is-lazy
for (lazy gather { take 42 }), # True
(lazy gather { loop { take 42 } }); # True
如果@
sigil'd 变量被赋值为returns True
用于调用.is-lazy
,赋值和变量是懒惰的。所以代码 @f1 = lazy gather ...
工作正常。
最后,序列 (1...Inf)
知道 它是惰性的,并告诉世界它是惰性的,不需要前缀 lazy
:
say .is-lazy with (1 ... Inf) # True
因此无论有无 lazy
.
,分配都可以正常工作
总而言之,如果分配给它的 Seq
表示它是惰性的,则 @
标记的变量会惰性地获得元素,否则会急切地获得元素。
你没有问这个,但另一种情况是将 Seq
分配或绑定到 $
印记变量,或印记自由标识符。
与 @
印记变量一样,在 $
印记变量或印记自由标识符上调用 .is-lazy
将 return True
或 False
符合 assigned/bound Seq
.
但是,不管是.is-lazy
return还是True
还是False
,Seq
仍然会 lazily.
迭代
在 Raku 文档中指出,收集-获取结构正在被惰性评估。在以下示例中,我很难得出关于构造的惰性的结论:
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;
在第一种情况下(将 Seq 分配给@f1)如果我们去掉 "lazy" 定义,那么生成的序列(使用 gather-take)永远是 运行(不是懒)。
在第二种情况下(将 Seq 分配给@f2)@f2 变得懒惰。
为什么我们的行为会有所不同?尽管我们尝试做同样的事情:以惰性方式将 Seq 分配给数组
有人可以澄清一下吗???
In Raku documentation it is stated that gather-take constructs are being lazy evaluated.
他们可以。但不一定。无论哪种方式,他们都非常乐意工作。
在一个关键的转折中,如果 gather
询问 是否懒惰,它 return 就会 False
。这就是导致您看到的行为的原因。
采取 #1:一种方式 gather
表现得 懒惰
gather
在需要时计算其序列中的下一个元素。这是 the classic definition of lazy evaluation, as described by Wikipedia:
lazy evaluation ... delays the evaluation of an expression until its value is needed
采取 #2:第二种方式 gather
表现得 懒惰
一些使用值序列的构造总是延迟使用它们。如果他们消费的序列是 gather
,他们会懒惰地要求它的值。在这种情况下 gather
有义务,评估其序列直到它达到 take
,然后 yielding 直到需要下一个值。
采取 #3:一种方式 gather
表现得 急切
一些消耗值序列的构造总是急切地消耗它们。如果他们正在消费的序列是 gather
,他们会急切地要求它的值。在这种情况下,gather
有义务,任何懒惰都是没有意义的。
采取#4:第二种方式gather
表现急切
一些使用值序列的构造根据序列对 .is-lazy
呼唤它;如果它 returns True
,那么它的值是惰性要求的,否则它们是急切要求的。
这里出现了一个关键的转折:当在 gather
构造上调用 .is-lazy
时,它 returns False
.
练习 #5:您的示例中发生了什么
say .is-lazy
for (gather { take 42 }), # False
(gather { loop { take 42 } }); # False
在您的 @f1 = gather ...
案例中,@f1
被分配了一个表明它 不是 惰性的序列。即使它包含无限循环也是如此。 @
sigil'd 变量将其视为 急切地 分配序列的提示 - 代码挂起。
前缀 lazy
创建了一个新的 Seq
,它懒惰地从其右侧的表达式中提取。它还 returns True
如果 .is-lazy
被调用:
say .is-lazy
for (lazy gather { take 42 }), # True
(lazy gather { loop { take 42 } }); # True
如果@
sigil'd 变量被赋值为returns True
用于调用.is-lazy
,赋值和变量是懒惰的。所以代码 @f1 = lazy gather ...
工作正常。
最后,序列 (1...Inf)
知道 它是惰性的,并告诉世界它是惰性的,不需要前缀 lazy
:
say .is-lazy with (1 ... Inf) # True
因此无论有无 lazy
.
总而言之,如果分配给它的 Seq
表示它是惰性的,则 @
标记的变量会惰性地获得元素,否则会急切地获得元素。
你没有问这个,但另一种情况是将 Seq
分配或绑定到 $
印记变量,或印记自由标识符。
与 @
印记变量一样,在 $
印记变量或印记自由标识符上调用 .is-lazy
将 return True
或 False
符合 assigned/bound Seq
.
但是,不管是.is-lazy
return还是True
还是False
,Seq
仍然会 lazily.