我正在研究迈克尔·皮尔奎斯特出色的州议会演讲here。我被困在54分钟,有两个问题。
如果ofs
是Option[FollowerStats]
,那么?
运算符是什么?一世
在Scala 2.10.2
最后一个生成器如何将更新的缓存(命中或未命中增加)放回checkCache方法的State
结果中?返回的State
似乎被丢弃,而理解似乎只能产生Option[FollowerStats]
def checkCache(u: String): State[Cache, Option[FollowerState]] = for {
c <- State.get[Cache]
ofs <- State.state {
c.get(u).collect {
case Timestamped(fs, ts) if !state(ts) => fs
}
}
_ <- State.put(ofs ? c.recordHit | c.recordMiss)
} yield ofs
试图理解我试图重新编写for comprehension,但它没有帮助。
State.get[Cache].flatMap{ c =>
State.state{c.get(u).collect(...)}.flatMap{ ofs =>
State.put(ofs ? c.recordHit | c.recordMiss).map{ _ =>
ofs
}
}
}
更新
由于答案,我认为我已经掌握了第2点的关键。我没有意识到收益率基本上是这样说:从s => (s,())
获取最后一个状态put
并将Unit
值类型替换为ofs,以获得s =>(s,ofs)
。我想关键是要意识到产量不是字面上的返回,但它被翻译为State.map。
更新 现在了解选项。我猜这个演示文稿仍然使用Scalaz的含义,尽管它衍生出状态monad。
答案 0 :(得分:2)
首先是三元运算符。
ofs ? c.recordHit | c.recordMiss
相当于:
if (ofs.isDefined) c.recordHit else c.recordMiss
或者:
ofs.fold(c.recordMiss)(_ => c.recordHit)
它由Scalaz提供,并作为隐式类(OptionOps
)实现,为?
提供Option
方法,返回Conditional
类,其|
}} 方法。在这种情况下,我不确定额外的简洁是否值得混淆,但人们使用它,所以值得了解。
对于状态更新,请考虑以下简化示例:
val inc: State[Int, Unit] = for { i <- get[Int]; _ <- put(i + 1) } yield ()
它可能首先看起来像我们“丢弃”状态并且仅产生单位,但inc
的值实际上是整个状态操纵计算(在这种情况下,一个不返回任何相关或有趣的价值),包括更新。
答案 1 :(得分:1)
?|
运算符来自scalaz的布尔语法。看看here at BooleanOps。它实际上是2个函数,?
上的|
然后Conditional
。
更新的缓存实际上是运行State
操作的结果。如果您在视频的前面看到,State
应该被定义为在给定状态操作和初始状态s
的情况下,使用s
运行状态操作会导致{(a, s2)
1}}这是一对:(a)从传入状态计算的值(在元组中表示为a
)和(b)在执行操作后的新状态(表示为{{ 1}})。
请注意,在通过monadic动作运行初始s2
之前,实际上并未计算新的Cache
。