del*_*ber 9 scala event-driven
为了澄清事件驱动我的意思,我指的是我所处的情况
def onTrade(...)
Run Code Online (Sandbox Code Playgroud)
每次特定股票交易时都会调用.假设我想跟踪每日最高交易价格.对我来说,明显的解决方案是:
var dailyHigh = 0
def onTrade(...) {
if (price > dailyHigh) dailyHigh = price
}
Run Code Online (Sandbox Code Playgroud)
有没有办法使用val代替var来实现这个功能?还假设我可能希望将来添加dailyLow,volumeHigh,volumeLow等.
实际上并不是什么大问题.一个完整的解决方案可能会使用Reader,IO和State monads以及Iteratee和镜头,但这里有一个更简单的版本:
case class State(dailyHigh: Int = 0)
object Main {
type Event = (State => State)
def mainLoop(currState: State, events: Stream[Event]): State =
if (events.nonEmpty) {
val newState = events.head(currState)
mainLoop(newState, events.tail)
} else currState
def onTrade(price: Int): Event = (s: State) =>
if (price > s.dailyHigh) s.copy(dailyHigh = price) else s
def main(args: Array[String]) {
val events = onTrade(5) #:: onTrade(2) #:: onTrade(10) #:: onTrade(5) #:: Stream.empty
val finalState = mainLoop(State(), events)
println(finalState)
}
}
Run Code Online (Sandbox Code Playgroud)
看,妈,没有变形!
当然,状态可能变得非常复杂,但这就是镜头的用武之地.使用镜头,可以很容易地查询和更改(复制新值)任意复杂的数据结构.
使用iteratees对于事件来说很自然 - 在一个非常简单的意义上,"onTrade"成为一个由枚举器调用的迭代器("生成"事件的东西),如果由部分函数组成,则可以折叠所有事件他们分成一个部分功能.
或者,State monads可以与IO monads结合使用以进行理解.
最后,还有延续选项.如果某些处理需要接收一系列事件,那么每个事件的结果可以是延续,并且延续本身也成为状态的一部分.
归档时间: |
|
查看次数: |
3444 次 |
最近记录: |