假设我有一个列表List[() => Int]
,需要调用所有函数来获取结果列表。
def invoke(fs: List[() => Int]): List[Int] = fs map (_())
如果fs
有重复怎么办?我可以记住结果,但我需要同时调用这些函数。看起来我需要做一些预处理以确保每个函数只被调用一次。
你会建议什么?
答案 0 :(得分:4)
一般来说,无法知道两个函数是否相等。即使您正在查看同一个函数实例的两个副本,它们也可能会调用一些副作用(例如生成一个随机数),因此在某种意义上忽略第二个调用是不正确的。在功能可证明没有副作用的情况下,JVM可能会自己解决这个问题。老实说,我认为你在这里解决了错误的问题。
但如果你真的想要记忆,我会使用scalaz Memo
。不同类型的Memo
记录了它们提供的线程安全性。
def execute(fs: List[() => Int]) = {
val m = Memo.mutableHashMapMemo({f: (() => Int) => f()})
fs map m
}
答案 1 :(得分:0)
可能正在使用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
的第一个成功响应初始化。