Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion docs/guards.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,37 @@ A conditional transition occurs only if specific conditions or criteria are met.

When a transition is conditional, it includes a condition (also known as a _guard_) that must be satisfied for the transition to take place. If the condition is not met, the transition does not occur, and the state machine remains in its current state or follows an alternative path.

This feature allows for multiple transitions on the same {ref}`event`, with each {ref}`transition` checked in the order they are declared. A condition acts like a predicate (a function that evaluates to true/false) and is checked when a {ref}`statemachine` handles an {ref}`event` with a transition from the current state bound to this event. The first transition that meets the conditions (if any) is executed. If none of the transitions meet the conditions, the state machine either raises an exception or does nothing (see the `allow_event_without_transition` parameter of {ref}`StateMachine`).
This feature allows for multiple transitions on the same {ref}`event`, with each {ref}`transition` checked in **declaration order** — that is, the order in which the transitions themselves were created using `state.to()`. A condition acts like a predicate (a function that evaluates to true/false) and is checked when a {ref}`statemachine` handles an {ref}`event` with a transition from the current state bound to this event. The first transition that meets the conditions (if any) is executed. If none of the transitions meet the conditions, the state machine either raises an exception or does nothing (see the `allow_event_without_transition` parameter of {ref}`StateMachine`).

```{important}
**Evaluation order is based on declaration order, not composition order.**

When using conditional transitions, the order of evaluation is determined by **when each transition was created** (the order of `state.to()` calls), **not** by the order they appear when combined with the `|` operator.

For example:

```python
# These are evaluated in DECLARATION ORDER (when state.to() was called):
last_checked = state_a.to(state_x) # Created FIRST → Checked FIRST
mid_checked = state_a.to(state_y) # Created SECOND → Checked SECOND
first_checked = state_a.to(state_z) # Created THIRD → Checked THIRD

# The | operator does NOT change evaluation order:
my_event = first_checked | mid_checked | last_checked
# Evaluation order is still: last_checked → mid_checked → first_checked
```

To control the evaluation order, declare transitions in the desired order:

```python
# Declare in the order you want them checked:
first = state_a.to(state_b, cond="check1") # Checked FIRST
second = state_a.to(state_c, cond="check2") # Checked SECOND
third = state_a.to(state_d, cond="check3") # Checked THIRD

my_event = first | second | third # Order matches declaration
```
```

When {ref}`transitions` have guards, it is possible to define two or more transitions for the same {ref}`event` from the same {ref}`state`. When the {ref}`event` occurs, the guarded transitions are checked one by one, and the first transition whose guard is true will be executed, while the others will be ignored.

Expand Down