懒惰计算的索引序列类型

9

我需要构建一系列从外部资源加载的对象序列。由于这种加载是一项昂贵的操作,需要延迟到对象被需要的时间才进行。在集合构建完成后,我需要对包含的对象进行索引访问。Scala标准库是否提供适用于此用例的集合?如果没有,那么实现它的最佳方法是什么?

编辑:
首选的索引查找应该是O(1)操作。

3个回答

10

奇怪的是,Miles最近在推特上谈论了这个。 一个回复指向scalaz中Name.scala文件末尾的Need,另一个回复指向specs的LazyParameter

使用Need进行少量测试:

import scalaz._
import Scalaz._
val longOp = { var x = 0; () => {println("longOp"); x += 1; x }}
val seq = Seq(Need(longOp()), Need(longOp()))
val sum = seq.map(_.value).sum
val sum = seq.map(_.value).sum

val v = Need(longOp())
val s = v.map("got " + _)
println(s.value)
println(s.value)

打印:

longOp: () => Int = <function0>
seq: Seq[scalaz.Name[Int]] = List(
  scalaz.Name$$anon$2@1066d88, scalaz.Name$$anon$2@1011f1f)
longOp
longOp
sum: Int = 3
sum: Int = 3
v: scalaz.Name[Int] = scalaz.Name$$anon$2@133ef6a
s: scalaz.Name[java.lang.String] = scalaz.Name$$anon$2@11696ec
longOp
got 3
got 3

所以longOp只在第一次访问值时调用一次。


非常感谢,我无法想起在哪里看过它。 - Nicolas
“Name” 似乎在每次访问时都要评估 “value”: http://paste.pocoo.org/show/464187/. 这是不可取的。 - missingfaktor
1
@missingfaktor,是的 - 在文件末尾使用Need隐藏。 - huynhjl
@huynhjl:哎呀,我以为那是一个打字错误。抱歉! - missingfaktor

5
据我所知,标准库中没有适合的内容。一种解决方案可能是使用一种Lazy包装器来处理您的对象:
class Lazy[A](operation: => A) {
  lazy val get = operation
}

然后,您可以使用任何您想要使用的集合构建Collection [Lazy[A]]


+1,这正是我目前所选择的。 (除了我的getunary_! :-) 我认为可能会有一些更好的替代方案,无论是在stdlib的某些隐藏角落中还是在Scalaz中。 - missingfaktor
可能是一些Scalaz的内容,我不太熟悉。 - Nicolas

2

看起来你需要一个


流是一个惰性列表,在流中进行索引访问是一项O(n)操作。我需要具有基于索引的查找的O(1)性能特征的东西。 - missingfaktor
1
你应该在你的问题中加入这个性能考虑因素。这是一个重要的元素。 - Nicolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接