DEV Community

Cover image for Unified State Expressions - Transitions (First Sketch)
rekreanto
rekreanto

Posted on • Updated on

Unified State Expressions - Transitions (First Sketch)

Some examples:

The traffic light. Now with behavior

Non-hierarchical Traffic Light


// State Machine Type
TrafficLight :> Green | Yellow | Red


// State Machine Reactions 
// Collapsed view
TrafficLight                   // scope
  ! NEXT                         // transition name

// State Machine Reactions
// expanded view
TrafficLight                   // scope
  ! NEXT : Green  -> Yellow      // reaction
  ! NEXT : Yellow -> Red         // reaction
  ! NEXT : Red    -> Green       // reaction


// State Machine Boundary Actions

TrafficLight
  :> 
  | Green  >> after(<duration>)( NEXT ) // boundary action
  | Yellow >> after(<duration>)( NEXT ) // boundary action
  | Red    >> after(<duration>)( NEXT ) // boundary action


Enter fullscreen mode Exit fullscreen mode

Counter

And the almost simplest counter from 15js:


// State Machine Type
Counter :> <int>


// State Machine Reactions
// collpased view
Counter                     // scope
  ! INCR                      // transition name
  ! RESET                     // transition name
  ! DECR                      // transition name

// State Machine Reactions
// expanded view
Counter                     // scope
  ! INCR  : : (  n ) => n + 1  // reaction
  ! RESET : : ( _n ) => 0      // reaction
  ! DECR  : : (  n ) => n - 1  // reaction

// Note that the reconstructor part is empty

Enter fullscreen mode Exit fullscreen mode

The Linksy Kitchen Timer

(It is the timer in the banner art above.)


// State Machine Type
LinksyKitchenTimer 
  :>
    | Setting :> ( <int min>, <int sec> )
    | Ticking :> ( <int sec> )
    | Paused  :> ( <int sec> )
    | Alarming.
Enter fullscreen mode Exit fullscreen mode
// State Machine Reactions

LinksyKitchenTimer // scope
    ! START   : Setting  -> Ticking  : ( m, s ) => m*60 + s  // reaction
    ! PAUSE   : Ticking  -> Paused   : ( s ) => s      
    ! CANCEL  : Paused   -> Setting  : <history> // residual state is memoized
    ! RESTART : Paused   -> Ticking  : ( s ) => s
    ! OK      : Alarming -> Setting  : <history> // residual state is memoized
    ! TIC     : Ticking  -> Alarming

LinksyKitchenTimer :> Ticking  // scope
  ! TIC : : gt(0) ( s ) => s-1  // reaction

LinksyKitchenTimer :> Setting  // scope
    ! M10 : : ( m, s ) = ( m+10, s ) // reaction
    ! M5  : : ( m, s ) = ( m+ 5, s )
    ! M3  : : ( m, s ) = ( m+ 3, s )
    ! M1  : : ( m, s ) = ( m+ 1, s )
    ! S10 : : ( m, s ) = ( m, s+10 )
Enter fullscreen mode Exit fullscreen mode
// State Machine Boundary Actions
LinksyKitchenTimer :> Ticking  // scope
  >> after( 1s )( TIC )          // boundary action

LinksyKitchenTimer :> Alarming  // scope
  >>  after( 30s )( OK )          // boundary action
  >> <start/stop sound>           // boundary action


Enter fullscreen mode Exit fullscreen mode

Separate definitions are preferred

The Behavior part seems to be 3-10 times larger than the State Type definitions if measured in SLOC. That, I think is a good argument for giving the type information separately; it might otherwise be less readable and less useful.

Top comments (0)