Skip to content

Transition Actions

Each transition can carry an action block written in braces right after the event name: A -> B on event { ... }. The block executes synchronously after the transition is decided, but before .send returns — ideal for side effects that are cohesive with the state change (logs, hardware pulses, animation triggers).

Door with four transitions, each printing a message when fired.

02-actions.zolo
Playground
// Feature: transition actions — code that runs on transition
// Syntax: `A -> B on event { <body> }`. The block runs after the
// transition is decided but before `.send` returns.
// When to use: side effects tied to state changes — log lines,
// hardware pulses, animation triggers, audio events.

machine Door {
  state Closed, Open, Locked
  initial Closed
  Closed -> Open on open { print("door opened") }
  Open -> Closed on close { print("door closed") }
  Closed -> Locked on lock { print("door locked") }
  Locked -> Closed on unlock { print("door unlocked") }
}

let door = Door.new()
print(door.state)  // expected: Closed

door.send("open")  // expected: door opened
print(door.state)  // expected: Open

door.send("close")  // expected: door closed
print(door.state)  // expected: Closed

door.send("lock")  // expected: door locked
print(door.state)  // expected: Locked

door.send("unlock")  // expected: door unlocked
print(door.state)  // expected: Closed

Keep the blocks small. For heavier work, prefer spawning a coroutine with spawn inside the action instead of blocking send.

enespt-br