Source mirror; https://github.com/g-pechorin/sstate.scala

Won’t actually build, use the full repository here

Releases (tags) https://github.com/g-pechorin/sstate.scala/tags

    "com.peterlavalle" %% "sstate" % ???



SState is a cute little pure-functional FSM class in Scala that I wrote after seeing JEasyStates. The only real advantage of mine is that it can (probably) be dropped into a Scala.JS project without any magic.

There’s a unit test at the foot of this doc showing how I test it.


  • machine sort of the class or kind defining the nature of the FSM
  • ghost some value that’s carried around by shell objects of the machine
    • ghost values can be changed when the shell reacts to an event
  • shell an instance of a machine which carries a ghost
    • yes; i’m proud of this naming
  • state a state which a shell can be in
    • I use case object in the demo, but, could use case class
  • event something that is/can be sent to the machine to trigger a change
    • I use case object in the demo, but, could use case class

Machines are immutable, so, when replacing a ghost durring a transition there’s no way to directly1 raise another event.


  1. create a machine with appropriate generic parameters
  2. add some states with addState(...) so that they can be used in transitions
  3. define what to do on transitions onEvent(...) to define actions to take on transitions
  4. use .transition as a shorthand for situations where the ghost doesn’t need to be changed
  5. keep adding events and handlers until you’ve captured the entirity of the FSM which you’re creating
  6. create a shell with apply(...) giving it an initial state and an intial ghost
  7. do what you will with this thing

In theory this system would be super-fun to orchestrate through a DSL or to use as the endpoint of some fearsome threaded goddess.

val machine =

    // start a new FSM
    Machine[Int, TEvent, TState]()

        // we can be in a state of LOCKED

        // we can be in a state of UNLOCKED

        // when we're LOCKED, if COIN then become UNLOCKED and modify our ghost
        .onEvent(MachineTest.Locked, MachineTest.Coin, MachineTest.UnLocked)(_ + 1)

        // when we're UNLOCKED, if PUSH, become LOCKED and don't do anything
        .transition(MachineTest.UnLocked, MachineTest.Push, MachineTest.Locked)

        // create an instance of the machine with a ghost=0
        // ... the machine
        .apply(MachineTest.Locked, 0)

  1. Various approaches which wrap this system are feasible, but, none are interesting to the author. [return]
Peter LaValle avatar
About Peter LaValle
honks at geese. speaks the byzantine languages that make the magic boxes do the things. Someday maybe I'll retire and be a graphics programmer or demoscene coder.
comments powered by Disqus