在Scala中,如何将事件驱动的编程与功能方法结合起来? [英] In Scala, how would I combine event driven programming with a functional approach?

查看:99
本文介绍了在Scala中,如何将事件驱动的编程与功能方法结合起来?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了弄清事件驱动的含义,我指的是我遇到的情况

To clarify what I mean by event driven I'm referring to a situation where I have

def onTrade(...)

每一次特定股票交易被称为哪个.假设我要跟踪每日最高交易价格.对我来说,显而易见的解决方案是:

Which is called every time a particular stock trades. Suppose I want to track the daily highest trade price. To me the obvious solution is:

var dailyHigh = 0

def onTrade(...) {
    if (price > dailyHigh) dailyHigh = price
}

是否有一种使用val而不是var来实现此功能的方法?还要假设我将来可能要添加DailyLow,volumeHigh,volumeLow等.

Is there a way to achieve this functionality using val instead of var? Assume also that I may want to add dailyLow, volumeHigh, volumeLow etc in the future.

推荐答案

实际上没有太大问题.完整的解决方案可能会使用Reader,IO和State monad以及Iteratee和lens,但这是一个更简单的版本:

Not much of a problem, actually. A full solution would probably use Reader, IO and State monads plus Iteratee and lenses, but here's a simpler version:

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)
  }
}

看,妈妈,没有变种!

当然,状态可能会变得非常复杂,但这就是镜头的用武之地.有了镜头,就可以轻松地查询和更改任意复杂的数据结构(使用新值进行复制).

State can become quite complex, of course, but that's where lenses come in. With lenses, it is pretty easy to consult and change (copy with new value) arbitrarily complex data structures.

对于事件来说,使用迭代器是很自然的-从简单的意义上说,"onTrade"成为一个迭代器,该迭代器由枚举器(生成"事件的东西)调用,并且每个事件都是由部分函数组成的,将它们全部折叠成一个局部函数.

Using iteratees is natural for events -- in a very simple sense, "onTrade" becomes an iteratee that gets invoked by an enumerator (the thing that "generates" the events) with each event if composed from partial function, you can fold all of them into a single partial function.

或者,可以将State单子与IO单子结合起来以产生理解.

Alternatively, State monads can be combined with IO monads on for-comprehensions.

最后,可以选择继续.如果某些处理要求接收一系列事件,那么每个事件的结果可以是连续的,并且连续本身也成为状态的一部分.

Finally, there's the option of continuations. If some processing requires a chain of events to be received, then the result of each event can be a continuation, and the continuation themselves become part of the state.

这篇关于在Scala中,如何将事件驱动的编程与功能方法结合起来?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆