0

我有一个任务:在消息“userStart”上启动计时器 5 秒,如果用户将在计时器之前发送答案 - >取消计时器。代码很简单,它可以工作,questin 是如何以 FP 方式制作它。据我了解,我应该使用“val”而不是“var”。我是 FP 的新手,所以如果有人能帮我解决这个问题,我会很高兴,或者推荐一些资源,我可以在其中找到如何做这些事情的简单示例。谢谢!

class Game extends Actor{

  var actsCount:Int = 0
  var timer:Option[Cancellable] = None

  def startTimer(): Unit = {
    timer = Some(context.system.scheduler.scheduleOnce(5 seconds, self, "userMissed"))
  }

  def receive = {
    case "userStart" => startTimer()
      sender() ! "do move"
    case "userAct" =>
      println("> user made his move")
      actsCount += 1
      if(timer.isDefined)
        timer.get.cancel()
    case "userMissed" => println("> user missed his move")
  }
}
4

2 回答 2

2

这是一个become用于跟踪接收函数中状态的版本:

class Game extends Actor{     
  def startTimer(): Cancellable = context.system.scheduler.scheduleOnce(5 seconds, self, "userMissed")

  def receive = idleReceive(0)

  def idleReceive(actsCount: Int): Actor.Receive = {
    case "userStart" => startTimer()
      context.become(waitingReceive(actsCount, startTimer()))
      sender() ! "do move"
  }

  def waitingReceive(actsCount: Int, timer: Cancellable): Actor.Receive = {
    case "userAct" =>
      println("> user made his move")
      context.become(idleReceive(actsCount + 1))
      timer.cancel()
    case "userMissed" =>
      println("> user missed his move")
      context.become(idleReceive(actsCount))
  }
}

需要更多错误处理,包括在传输“userAct”消息时触发计时器的竞争条件。您还需要添加另一条消息来检索 的值actsCount

于 2018-06-26T11:58:44.400 回答
2

如评论中所述:您的特定用例本质上是状态完整的,并且已经封装在一个Actor允许远离纯功能范式的一些自由中。

但是,如果您仍然对自己的设计不满意,有几个选择:

有限状态机

Akka 提供了允许 Actor 像 FSM 一样行为的机制。事实上,文档中的示例看起来非常像您的 Actor。

成为/不成为

Actors 也有能力根据传入的消息改变他们的receive方法。你的时间逻辑可以嵌入到成为 & unbecome 逻辑中。

于 2018-06-26T11:59:49.993 回答