【问题标题】:Lazily evaluated indexed sequence type惰性求值的索引序列类型
【发布时间】:2011-11-03 10:39:27
【问题描述】:

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

编辑:
索引查找最好是 O(1) 操作。

【问题讨论】:

    标签: scala collections lazy-evaluation scala-collections


    【解决方案1】:

    奇怪,迈尔斯最近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 似乎在每次访问时评估 valuepaste.pocoo.org/show/464187。这是不可取的。
    • @missingfaktor,是的 - 使用隐藏在文件末尾的 Need
    • @huynhjl:糟糕,我还以为是错字。对不起!
    【解决方案2】:

    据我所知,标准库中没有任何内容。一种解决方案可能是为您的对象使用一种惰性包装器:

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

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

    【讨论】:

    • +1,这正是我目前所接受的。 (除了我的 getunary_! :-) 我认为可能有更好的选择,无论是在 stdlib 的一些隐藏角落还是在 Scalaz 中。
    • 可能是scalaz中的一些,我不熟悉。
    【解决方案3】:

    听起来你想要Stream

    【讨论】:

    • Stream 是惰性列表,流中的索引访问是 O(n) 操作。我想要具有 O(1) 性能特征的基于索引的查找。
    • 您应该将此性能考虑添加到您的问题中。这是一个重要的元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-06
    • 2017-11-01
    • 1970-01-01
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多