【问题标题】:how to explain the behaviour of this FSM example?如何解释这个 FSM 示例的行为?
【发布时间】:2016-09-02 19:53:18
【问题描述】:

我正在尝试理解 akka FSM 模式,在下面的示例中,我不明白为什么我没有得到对应于处理的打印 -> 完成。我的印刷品清楚地表明我已经完成了。有人可以启发我吗?

import akka.actor.{ActorRef, FSM}
import scala.concurrent.duration._
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.FSM.Event
import akka.actor.Props

object FSM2 extends App{
  val system = ActorSystem("test")
  val test = system.actorOf(Props[Test], "t")
  test ! Set("hello")
}

sealed trait State
case object idle extends State
case object processing extends State
case object complete extends State

sealed trait Data
case class Content(processing:Int) extends Data

class Test extends FSM[State, Data]{

  when(idle) {
    case Event(test:Set[String], _) => {
      goto(processing) using Content(test.size-1)
    }
 }
  when(processing, stateTimeout = 1 second) {
     case Event(StateTimeout, Content(count)) => {
     println(count)
     count match {
        case 0 => goto(complete) using Content(0)
        case _ => stay using Content(count)
     }
    }
  }
  when (complete, stateTimeout = 1 second) {
    case Event(StateTimeout, _) => {
      println("in complete")
      goto(idle) using Content(0)
    }
 }

  onTransition({
    case idle -> processing => {
    println("idle -> processing")
  }
  case processing -> complete => {
      println("processing -> complete")
  }
  })

  startWith(idle, Content(0))
  initialize()
}
output:
idle -> processing
idle -> processing
0
idle -> processing
in complete
idle -> processing

I thought this would be the expected output:

idle -> processing
0
idle -> processing
processing -> complete
in complete
(go back to idle with no print)

我写的一些其他代码表明它不执行模式匹配,而是执行赋值。

如果我在状态对象(空闲、处理、完成和空闲 -> 处理等)上使用大写字母,它会起作用。

【问题讨论】:

    标签: scala akka fsm


    【解决方案1】:

    主要问题是,case idle -> processing 与您的案例对象不匹配,而是与任何对象匹配,并将这些对象绑定到名称 idleprocessing。为了匹配这些 case 对象,您必须匹配一个稳定的标识符,这意味着要么以大写字母开头 case 对象(正如您已经观察到的),要么在匹配中用反引号将它们包围:

    case `idle` -> `processing`
    

    考虑到这一点,应该清楚字符串 "idle -> processing" 会针对每个状态转换打印,而不仅仅是从空闲到处理的那些,您可以通过打印 println(s"$idle -> $processing") 来验证这一点。

    output:
    idle -> processing // triggered by initialize(), is actually idle -> idle
    idle -> processing // the actual idle -> processing transition
    0
    idle -> processing // processing -> complete
    in complete
    idle -> processing // complete -> idle
    

    【讨论】:

    • 你也可以通过将你的case对象重命名为大写来解决这个问题:'Processing'、'Idle'等。这样编译器会尝试匹配它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多