scala - 如何使用`flatMap`实现延迟计算的成本估算?
问题描述
我已经实现了一个带有Calculation
2 个参数的类:一个计算输入,它是一个按名称调用的参数,也是一个成本。当我尝试flatMap
计算时,它的第一部分被执行。是否有可能推迟一切flatMap
并仍然提供总成本?
class Calculation[+R](input: => R, val cost: Int = 0) {
def value: R = input
def map[A](f: R => A): Calculation[A] =
new Calculation(f(input), cost)
def flatMap[A](f: R => Calculation[A]): Calculation[A] = {
val step = f(input)
new Calculation(step.value, cost + step.cost)
}
}
object Rextester extends App {
val f1 = new Calculation({
println("F1")
"F1"
})
val f2 = f1.flatMap(s => new Calculation({
println("F2")
s + " => F2"
}))
println(f2.cost)
}
一旦f2
被声明(flatMap
被调用),我们可以看到将打印“F1”。打印的成本是"15"
,这是正确的,但我希望完全推迟实际计算,这意味着我f1
在计算成本时不应该看到正在执行的操作。
解决方案
您只需要多一点懒惰,这样就不会急切地评估成本flatMap
:
class Calculation[+R](input: => R, c: => Int = 0) {
def value: R = input
lazy val cost: Int = c
def map[A](f: R => A): Calculation[A] =
new Calculation(f(input), cost)
def flatMap[A](f: R => Calculation[A]): Calculation[A] = {
lazy val step = f(value)
new Calculation(step.value, cost + step.cost)
}
}
请注意,这可能仍然不具有您想要的语义(例如f2.value
,连续调用两次将导致两者都F1
被F2
打印,第一次打印,并且仅第二次打印),但它确实可以防止在定义F2
时发生副作用。f2
推荐阅读
- webgl2 - 使用 UBO 进行 WebGL2 实例化
- python - 如何在示例 xml 中按剧集 ID 对系列进行排序
- javascript - 在 html 中添加 4.5 + .525 = 5.025 时,我得到 4.5.525
- c# - 为属性绑定 DependencyProperty 是子样式 ComboBox
- python - 如何从 Spark DataFrame 中检索路径,然后在 spark.read 中使用它?
- mysql - MySQL 8 带有 Window 关键字的查询概率
- next.js - 为什么 next.js 在每次加载页面时调用 getStaticPaths?
- ngrx - 如何处理ngrx中的复杂对象?
- javascript - 在 jquery 过滤器中隐藏()之后的 Masonry.js 异常行为
- vaadin - 当条件为假时,dom-if 元素不隐藏