【问题标题】:List of functions with duplicates具有重复项的函数列表
【发布时间】:2015-02-25 20:05:25
【问题描述】:

假设我有一个列表List[() => Int],需要调用所有函数来获取结果列表。

def invoke(fs: List[() => Int]): List[Int] = fs map (_())

如果fs 有重复项怎么办?我可能可以记住结果,但我需要同时调用这些函数。看起来我需要做一些预处理来确保每个函数只被调用一次。

你有什么建议?

【问题讨论】:

    标签: list function scala concurrency


    【解决方案1】:

    一般来说,没有办法知道两个函数是否相等。即使您正在查看同一函数实例的两个副本,它们也可能会引发一些副作用(例如生成随机数),因此在某种意义上省略第二次调用是不正确的。在可证明该函数没有副作用的情况下,JVM 可能会自己解决这个问题。所以老实说,我认为你在这里解决了错误的问题。

    但如果你真的想记住,我会使用 scalaz Memo。不同类型的 Memo 记录了它们提供的线程安全保证。

    def execute(fs: List[() => Int]) = {
      val m = Memo.mutableHashMapMemo({f: (() => Int) => f()})
      fs map m
    }
    

    【讨论】:

    • 谢谢。我的实际问题有点不同。我有一个请求列表,并同时对这些请求执行远程调用。为简单起见,我更改了问题定义。
    • 感谢您顺便提及Memo。我会读一读。
    【解决方案2】:

    可能正在使用lazy:

    def foo1(): Int = { println("f1"); 1 }
    def foo2(): Int = { println("f2"); 2 }
    
    def toLazy(f: () => Int): () => Int = {
      lazy val res = f()
      () => res
    }
    
    val f1 = toLazy(foo1)
    val f2 = toLazy(foo2)
    
    val flist = List(f1, f2, f1)
    
    println("invoking...")
    val res = invoke(flist)
    println(res)
    
    // invoking...
    // f1
    // f2
    // List(1, 2, 1)
    

    如果 f1 请求失败并且您处理 Exception 以允许调用链继续进行,则 f1 的惰性将由 f1 的第一个成功响应初始化。

    【讨论】:

      猜你喜欢
      • 2019-02-04
      • 2022-11-30
      • 1970-01-01
      • 2018-04-12
      • 2021-01-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多