9

I need to build a sequence of objects that are loaded from an external resource. This loading being an expensive operation needs to be delayed until the time the objects are needed. After the collection is built, I need an indexed access to the contained objects. Does Scala standard library provide a collection suited to this use case? If not, what will be the best way to implement it?

Edit:
The indexed lookup should preferably be an O(1) operation.

missingfaktor
  • 90,905
  • 62
  • 285
  • 365

3 Answers3

10

Strange, Miles recently tweeted about this. A reply then points out to Need at the end of Name.scala in scalaz and another one points to specs' LazyParameter.

Little testing with 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)

prints:

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

So longOp is only called once on first access of value.

huynhjl
  • 41,520
  • 14
  • 105
  • 158
5

To my knowledge, there's nothing that fit in the standard library. A solution might be to use a kind of Lazy wrapper for your objects:

class Lazy[A](operation: => A) {
  lazy val get = operation
}

And then you can build your Collection[Lazy[A] with any kind of collection you want to use.

Nicolas
  • 24,509
  • 5
  • 60
  • 66
  • +1, That's exactly what I have currently settled for. (Except that my `get` is `unary_!` :-) I thought there might be some better alternative, either in some hidden corners of stdlib or in Scalaz. – missingfaktor Aug 25 '11 at 08:20
  • It might be some in scalaz, i'm not familiar with it. – Nicolas Aug 25 '11 at 08:22
2

It sounds like you want a Stream.

pr1001
  • 21,727
  • 17
  • 79
  • 125
  • Stream is a lazy list, and indexed access in a stream is an `O(n)` operation. I want something with `O(1)` performance characteristics for index-based lookup. – missingfaktor Aug 25 '11 at 07:52
  • 1
    you should add this performance consideration to your question. It's an important element. – Nicolas Aug 25 '11 at 08:05