我对Scala完全陌生。我一直在玩LazyLists。请考虑以下几点:
val fun: Int => Int = (x: Int) => {
println("PROCESSING...")
x + 1
}
val lazyList = LazyList(fun(1), fun(2), fun(3))上面的片段打印了三次"PROCESSING...",这表明计算了LazyList的所有三个元素。我发现这样的行为对于懒惰的收藏家来说是相当出乎意料的。所以,我决定印出来:
println(lazyList) // which prints "LazyList(<not computed>)".我以为它会打印出LazytList(2, 3, 4)。(我不完全确定,但在我看来,Scala的println为惰性集合工作了,有点像GHCi中的:sprint命令,将集合分为两部分:计算的和未计算的。)
下面是我的问题,关于这个代码:
"PROCESSING..."到底是关于什么的呢?如果没有,为什么println会这么说呢?LazyList的参数(比如fun(1) )?为什么在初始化时放弃call-by-need策略?还有其他发生这种事情的情况吗?请注意,当我们使用map而不是像预期的那样手动写下来时,不会产生输出。发布于 2021-05-26 11:50:36
以下任何一项工作(不对其参数进行评估)都不使用LazyList.apply:
LazyList.tabulate(3)(fun)fun(1) #:: fun(2) #:: fun(3) #:: LazyList.emptyLazyList.range(1, 4).map(fun)LazyList的参数(比如fun(1) )?为什么在初始化时放弃call-by-need策略?还有其他发生这种事情的情况吗?请注意,当我们使用map而不是像预期的那样手动写下来时,不会产生输出。我不认为应该立即计算fun(1),但这是因为您使用LazyList.apply来构造您的列表。LazyList(fun(1), fun(2), fun(3))是LazyList.apply(fun(1), fun(2), fun(3))的语法糖,该函数的类型签名是def apply[A](elems: A*): LazyList[A]。注意,该函数的参数不是按名称调用的。
那么:为什么LazyList.apply没有用逐名参数来定义?
def apply实际上来自于SeqFactory,它被混合到大多数集合伴生对象中。LazyList伙伴对象可能是集合库中的一个位置,其中的伙伴对象apply不是一个有用的添加。"PROCESSING..."到底是关于什么的呢?如果没有,为什么println会这么说呢?LazyList只知道什么时候计算元素,因为您通过在LazyList中访问它们来强制它们。在使用LazyList.apply的情况下,会发生以下情况:
LazyList.apply最初被调用时,将计算这些参数。LazyList.apply调用LazyList.from,它将通过延迟迭代步骤1中实现的中间Seq创建LazyList。到步骤2完成时,LazyList不知道其内容是否已被评估。此外,列表的脊柱本身是未评估的。
:sprint in GHCi并不是一个很好的比较,因为它在理解事物何时被评估时更加无所不知。它通过爬行运行时堆和在跨块运行时打印_来做到这一点。相比之下,println只是调用LazyList#toString,这是一个普通的Scala方法。
发布于 2021-05-15 20:12:48
尝试使用#::构造函数
scala> fun(1) #:: fun(2) #:: LazyList.empty
val res0: scala.collection.immutable.LazyList[Int] = LazyList(<not computed>)#::采用名参数,而LazyList.apply则采用按值表示的参数。
发布于 2021-05-27 07:55:53
我想你是混合了两个问题。元素的计算和打印。举个更简单的例子,你有:
val lazyList = LazyList(1, 2, 3)产出:
println(lazyList)将是:
LazyList(<not computed>)虽然这些值是明确计算出来的。
当打印惰性列表时,我们实际上调用了LazyList.toString,它调用addStringNoForce。正如我们所看到的,只要状态未定义,我们就能得到标准的LazyList(<not computed>)。为了使状态变为真,我们必须对成员state进行调用。有几种方法可以做到这一点。例如,在路上要调用head。请注意,这将导致第一个元素物化,而不是延迟列表的其余部分。
例如。守则:
val lazyList = LazyList(1, 2, 3)
lazyList.head
println(lazyList)将产出:
LazyList(1, <not computed>)以及以下各点:
val lazyList = LazyList(1, 2, 3)
lazyList.tail.head
println(lazyList)将产出:
LazyList(1, 2, <not computed>)您看到PROCESSING...输出的原因与LazyList完全无关。如果您调用fun(1),而不使用LazyList,则会得到相同的信息。
https://stackoverflow.com/questions/67550532
复制相似问题