【发布时间】:2011-11-03 10:39:27
【问题描述】:
我需要构建一系列从外部资源加载的对象。这种加载是一项昂贵的操作,需要延迟到需要对象的时间。构建集合后,我需要对包含的对象进行索引访问。 Scala 标准库是否提供适合此用例的集合?如果没有,最好的实施方式是什么?
编辑:
索引查找最好是 O(1) 操作。
【问题讨论】:
标签: scala collections lazy-evaluation scala-collections
我需要构建一系列从外部资源加载的对象。这种加载是一项昂贵的操作,需要延迟到需要对象的时间。构建集合后,我需要对包含的对象进行索引访问。 Scala 标准库是否提供适合此用例的集合?如果没有,最好的实施方式是什么?
编辑:
索引查找最好是 O(1) 操作。
【问题讨论】:
标签: scala collections lazy-evaluation scala-collections
奇怪,迈尔斯最近tweeted about this。然后回复指出 Need 在 scalaz 中 Name.scala 的末尾,另一条回复指向规范的 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 只在第一次访问值时被调用一次。
【讨论】:
Name 似乎在每次访问时评估 value:paste.pocoo.org/show/464187。这是不可取的。
据我所知,标准库中没有任何内容。一种解决方案可能是为您的对象使用一种惰性包装器:
class Lazy[A](operation: => A) {
lazy val get = operation
}
然后您可以使用您想使用的任何类型的集合来构建您的Collection[Lazy[A]。
【讨论】:
get 是 unary_! :-) 我认为可能有更好的选择,无论是在 stdlib 的一些隐藏角落还是在 Scalaz 中。
听起来你想要Stream。
【讨论】:
O(n) 操作。我想要具有 O(1) 性能特征的基于索引的查找。