### Clojure: Require clj-statecharts Core Namespace Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/get-started.md This snippet demonstrates how to include the `clj-statecharts.core` namespace in your Clojure project, aliasing it as `fsm` for convenient access to its state machine functionalities. This is a prerequisite for using the library's APIs. ```Clojure (require '[statecharts.core :as fsm]) ``` -------------------------------- ### APIDOC: Initialize State Machine (Immutable API) Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/get-started.md The `fsm/initialize` function is used to obtain the initial state of a defined state machine. By default, it triggers and executes all entry actions associated with the initial states. An optional `{:exec false}` parameter can be provided to prevent immediate execution, instead collecting the actions in the `_actions` key of the returned state map for later inspection or assertion. ```APIDOC (fsm/initialize machine) (fsm/initialize machine {:exec false}) ``` -------------------------------- ### APIDOC: Transition State Machine State (Immutable API) Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/get-started.md The `fsm/transition` function computes the next state of a machine based on its current state and a given event. It automatically executes all entry, exit, and transition actions involved in the state change. Similar to `initialize`, passing `{:exec false}` as an option will prevent immediate action execution, collecting them instead. ```APIDOC (fsm/transition machine state event) (fsm/transition machine state event {:exec false}) ``` -------------------------------- ### XState State Object Structure Example Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/xstate.md Illustrates the typical structure of a state object in XState, which includes separate `value` and `context` keys. The `context` holds application-specific data as a plain JavaScript map. ```js { value: "waiting", context: { user: "jack", backoff: 3000 } } ``` -------------------------------- ### Clojure Statechart Definition with State Identifier Examples Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/identifying-states.md This Clojure code snippet demonstrates various ways to specify target states in statechart transitions. It illustrates absolute paths (e.g., `[:> :s2]`), relative paths (e.g., `[:. :s1.1]`), and shorthand keyword references (e.g., `:s2`). The example also shows how an omitted or `nil` target signifies an internal self-transition, where actions are executed without changing the current state. ```Clojure {:states {:s1 {:on {:event1_2 :s2 ;; (1) :event_1_1.1 [:. :s1.1]} ;; (2) :states {:s1.1 {:on {:event1.1_1.2 :s1.2 :event1.1_2 [:> :s2] ;; (3) }}}} :s2 {:on {:event_2_2 {:actions some-action}}}}} ;; (4) ``` -------------------------------- ### Clojure State Map Structure Example Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/concepts.md This Clojure code snippet demonstrates the typical structure of a state map in clj-statecharts. It shows how internal keys (prefixed with an underscore, like `_state`) are used by the library, while other keys represent application-specific context data. Application code can read internal keys but should not modify them. ```clojure {:_state :waiting :user :jack :backoff 3000} ``` -------------------------------- ### Clojure State Machine Internal and External Transitions Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/transitions.md Explains the difference between internal and external transitions in clj-statecharts. Internal transitions do not trigger parent state entry/exit actions, while external transitions do, illustrated with examples using relative and absolute target syntax. ```clojure {:states {:s1 {:initial :s1.1 :entry entry1 :exit exit1 :on {:event1_1.2_internal [:. :s1.2] ;; (1) :event1_1.2_external [:> :s1 :s1.2]} ;; (2) :states {:s1.1 {} :s1.2 {}}}}} ``` -------------------------------- ### Update State Context with `assign` in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Explains how actions can modify the state machine's context using the `statecharts.core/assign` function, providing an example of updating a counter in Clojure statecharts. ```Clojure (require '[statecharts.core :as fsm :refer [assign]]) (defn update-counter [state event] (update state :counter inc)) {:states {:state1 {:on {:some-event {:target :state2 :action (assign update-counter)}}}}} ``` -------------------------------- ### Clojure State Machine Definition with Eventless Transitions Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/transitions.md This Clojure code snippet illustrates the definition of a state machine that incorporates eventless transitions. Eventless transitions are specified under the ':always' key within a state node, allowing for immediate state changes based on guard conditions upon entering that state. The example demonstrates how states like ':s2' can transition to ':s3' or ':s4' without an explicit event, depending on the evaluation of 'guard23' or 'guard24' respectively, and outlines the sequence of actions (entry/exit/custom actions) during such transitions. ```clojure {:states {:s1 {:entry entry1 :exit exit1 :on {:e12 :s2 :actions action12}} :s2 {:entry entry2 :exit exit2 :always [{:guard guard23 :target :s3 :actions action23} {:guard guard24 :target :s4 :actions action23}] :on {:e23 :s3}} :s3 {:entry entry3} :s4 {}}} ``` -------------------------------- ### Implement Dynamic Delay for Clojure Statechart Transitions Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/delayed.md Shows how to use a custom Clojure function to calculate the delay for a state transition dynamically. This example provides `calculate-backoff` for exponential backoff and `update-retries` for state updates, integrating them into a state machine definition for scenarios like websocket reconnection. ```Clojure (defn calculate-backoff "Exponential backoff, with a upper limit of 15 seconds." [state & _] (-> (js/Math.pow 2 (:retries state)) (* 1000) (min 15000))) (defn update-retries [state & _] (update state :retries inc)) ;; Part of the machine definition {:states {:connecting {:entry try-connect :on {:success-connect :connected}} :disconnected {:entry (assign update-retries) :after [{:delay calculate-backoff :target :connecting}]} :connected {:on {:connection-closed :disconnected}}}} ``` -------------------------------- ### Dispatching Re-frame Events with Epoch for Stale Event Discarding Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/integration/re-frame.md This example demonstrates how to dispatch re-frame events, optionally including an `:epoch` key, when integrating `clj-statecharts` with re-frame. When `epoch?` is enabled in the machine configuration, events dispatched with an `:epoch` value will only be processed if their epoch matches the current `_epoch` value in the state machine's state, effectively discarding stale events from previous asynchronous operations. ```Clojure (ajax/send {:url "http://image.com/imageA" ;; this event is always accepted :callback #(rf/dispatch [:viewer/fsm-event :success-load %])}) (ajax/send {:url "http://image.com/imageA" ;; For this event, when the callback is called, if the provided ;; epoch is not the same as the state's current _epoch value, the ;; event would be ignored. :callback #(rf/dispatch [:viewer/fsm-event {:type :success-load :epoch 1} %])}) ``` -------------------------------- ### Clojure State Machine Transitions with Multiple Actions and Simplified Syntax Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/transitions.md Demonstrates advanced syntax for defining state machine transitions, including specifying multiple action functions as a vector and simplifying transitions without actions to a single keyword. ```clojure {:states {:s1 {:on {:event1 {:target :s2 :actions [action-fn1 action-fn2]} ;; (1) :event2 :s3}}}} ;; (2) ``` -------------------------------- ### Defining Basic State Machine Transitions in Clojure Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/transitions.md Illustrates the fundamental structure of a state machine transition in clj-statecharts, showing how an event triggers a target state change and executes an action function. ```clojure {:states {:s1 {:on {:event1 {:target :s2 :actions some-action-fn}}}} ``` -------------------------------- ### Define Single Transition Action in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Illustrates how to define a single action that executes when a state transition occurs, using the full form of a transition target in Clojure statecharts. ```Clojure {:on {:some-event {:target :some-state :actions some-action}}} ``` -------------------------------- ### Define Multiple Transition Actions in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Shows how to define multiple actions to be executed sequentially during a state transition by providing a vector of actions in Clojure statecharts. ```Clojure {:on {:some-event {:target :some-state :actions [action1 action2]}}} ``` -------------------------------- ### Define Single Entry and Exit Actions for Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Illustrates how to define single actions that are executed specifically when entering or exiting a state in Clojure statecharts. ```Clojure {:states {:state1 {:entry some-action-on-entry :exit some-action-on-exit :on {...}}}} ``` -------------------------------- ### Define Multiple Entry/Exit Actions in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Demonstrates how to specify multiple entry or exit actions as a vector, ensuring they are executed in order within Clojure statecharts. ```Clojure {:states {:state1 {:entry [action1 action2] :exit [action3 action4] :on {...}}}} ``` -------------------------------- ### Integrating clj-statecharts Immutable API with Re-frame Event Handlers Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/integration/re-frame.md This snippet demonstrates how to set up a `clj-statecharts` machine to integrate with re-frame's immutable API. It shows the use of `statecharts.integrations.re-frame/integrate` to automatically register re-frame event handlers for machine initialization (`:mymodule/init`) and state transitions (`:mymodule/fsm-transition`), simplifying the management of state machine state within the re-frame `app-db`. ```Clojure (ns mymodule (:require [re-frame.core :as rf] [statecharts.core :as fsm] [statecharts.integrations.re-frame :as fsm.rf])) (def mymodule-path [(rf/path :mymodule)]) (def my-machine (-> (fsm/machine {:id :mymodule :initial :init :states {...} :integrations {:re-frame {:path mymodule-path ;; (1) :initialize-event :mymodule/init :transition-event :mymodule/fsm-transition}}}) (fsm.rf/integrate) ;; (2) )) ``` -------------------------------- ### clj-statecharts Flat State Map Structure Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/xstate.md Demonstrates the flat map structure used in clj-statecharts for representing state. Keys prefixed with an underscore, like `_state`, are internal, while other keys store application-specific data, similar to XState's context. ```clojure {:_state :waiting :user "jack" :backoff 3000} ``` -------------------------------- ### Configure Hugo Page Front Matter Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/archetypes/default.md This snippet illustrates a standard Hugo front matter block used to define metadata for a content page. It dynamically sets the page title by replacing hyphens in the file name, assigns the current date, and marks the page as a draft, preventing it from being published until ready. ```Go Template --- title: "{{ replace .Name "-" " " | title }}" date: {{ .Date }} draft: true --- ``` -------------------------------- ### Pass Additional Event Data to Clojure Statecharts Transitions Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/actions.md Shows how to include extra key-value pairs in the event argument when calling `fsm/transition`, making this data available to action functions in Clojure statecharts. ```Clojure (let [event {:type :some-event :k1 :v1 :k1 :v2}] (fsm/transition machine current-state event)) ``` -------------------------------- ### Defining a Parallel State Node in Clojure Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/parallel-states.md This Clojure code snippet demonstrates how to define a parallel state node within a statechart. It illustrates a file management application with three concurrent regions: `:main` (for file listing), `:props` (for file properties), and `:comments`. The `:type :parallel` key identifies the node as a parallel state, and child regions are defined under the `:regions` key, each acting as a hierarchical state node with its own initial state and transitions. ```Clojure {:id :file-app :type :parallel :context {:selected-file-name nil} :regions {:main {:initial :loading :states {:loading {:on {:success-load-files :loaded :fail-load-files :load-failed}} :loaded {} :load-failed {}}} :props {:initial :idle :states {:idle {:on {:file-selected :loading}} :loading {:on {:success-load-props :loaded :fail-load-props :load-failed}} :loaded {} :load-failed {}}}} :comments {:initial :idle :states {:idle {:on {:show-comments :loading}} :loading {:on {:success-load-comments :loaded :fail-load-comments :load-failed}} :loaded {} :load-failed {}}}} ``` -------------------------------- ### Implementing Guarded Transitions in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/guards.md This Clojure code demonstrates how to define a guarded transition within a statechart. A `:guard` key is added to a transition map, referencing a boolean function (`my-condition-fn`) that determines the target state. If the guard function returns true, the first target (`:s2`) is chosen; otherwise, the subsequent transition (`:s3`) is selected. ```Clojure (defn my-condition-fn [state event] ;; returns a boolean ) ;; Part of the machine definition {:states {:s1 {:on {:some-event [{:target :s2 :guard my-condition-fn :actions some-action} {:target :s3}]}}}} ``` -------------------------------- ### Define Basic Delayed Transitions in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/delayed.md Illustrates how to configure a state transition to occur automatically after a fixed delay using the `:after` keyword in a Clojure statechart definition. It demonstrates the inclusion of guards and actions for these time-based transitions. ```Clojure {:states {:s1 {:after [{:delay 1000 :target :s2 :guard some-condition-fn :actions some-action} {:delay 2000 :target :s3 :actions some-action}]}}} ``` -------------------------------- ### Use Simulated Clock for Time-Dependent Logic in Clojure Statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/delayed.md Provides guidance on accessing the current time within Clojure statechart actions to ensure unit-testability. It advises against using OS-specific time APIs like `(js/Date.now)` or `(System/currentTimeMillis)` and instead recommends `(statecharts.clock/now)` to integrate with the statecharts' simulated clock. ```Clojure ;; Recommended for unit-testable statecharts (statecharts.clock/now) ;; Avoid in statechart actions for unit testing ;; (js/Date.now) ;; (System/currentTimeMillis) ``` -------------------------------- ### Defining Hierarchical Parallel State Nodes in Clojure Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/parallel-states.md This Clojure code snippet demonstrates how to define a complex statechart with hierarchical and nested parallel nodes using the `clj-statecharts` library. It shows the use of the `:regions` key for parallel nodes and how they can be nested within other hierarchical states, such as `:p2b2` being a parallel node within `:p2.b`. ```clojure {:id :hierarchical-parallel-demo :initial :p2 :states ;; (1) {:p1 ;; (2) {:initial :p11 :states {:p11 {:on {:e12 :p12}} :p12 {}}} ;; p2 is a hierarchical parallel node :p2 ;; (3) {:type :parallel :regions {:p2.a ;; (4) {:initial :p2.a1 :states {:p2.a1 {:on {:e12 :p2.a2}} :p2.a2 {}}} :p2.b ;; (5) {:initial :p2b2 :states {:p2b1 {:on {:e231 :p2b2}} ;; parallel nest level depth +1 :p2b2 {:type :parallel ;; (6) :regions {:p2b2.a {:initial :p2b2.a1 :states {:p2b2.a1 {}}} :p2b2.b {:initial :p2b2.b1 :states {:p2b2.b1 {}}}}}}}}}}} ``` -------------------------------- ### Configuring Epoch Support for Stale Event Discarding in Re-frame Integration Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/integration/re-frame.md This configuration snippet illustrates how to enable the `epoch?` flag within the `re-frame` integration settings of a `clj-statecharts` machine. This feature helps prevent 'flaky' UI experiences in asynchronous scenarios (e.g., rapid image loading) by allowing the state machine to automatically discard events that belong to a previous 'epoch' or interaction cycle, ensuring only relevant events from the current user intent are processed. ```Clojure (-> (fsm/machine {:id :image-viewer :states {...} :integrations {:re-frame {:transition-event :viewer/fsm-event :epoch? true ;; (1) ...}}}) (fsm.rf/integrate)) ``` -------------------------------- ### Define Hierarchical States in Clojure for a Calculator Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/hierarchical-states.md This Clojure code snippet illustrates the definition of a statechart for a calculator, showcasing the use of hierarchical states. It demonstrates how a global event like `:clear-screen` can be handled at the root `:calculator` state, while specific sub-states like `:operand1`, `:operator`, and `:operand2` manage their own transitions based on digit input and operations. This structure effectively centralizes common event handling and prevents state explosion. ```Clojure {:id :calculator :on {:clear-screen {:target :operand1 :actions (assign reset-inputs)}} {:states {:operand1 {:on {:input-digit :operand1 :input-operator :operator}} :operator {:on {:input-operator :operand2}} :operand2 {:on {:input-digit :operand2 :equals :result}}}}} ``` -------------------------------- ### State Representation for Parallel Nodes in clj-statecharts Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/parallel-states.md This section describes how the current state of a finite state machine is represented when parallel nodes are involved in clj-statecharts. It covers both cases: when the root node is parallel, and when a nested node is parallel, illustrating the map-based representation for parallel regions. ```APIDOC - If the fsm root node is a parallel node, then the whole state is represented as a map, e.g. {:r1 :r1-state :r2 :r2-state} - In a typical hierarchical node, the current state is represented as [:s1 :s1.1]. However, if :s1.1 is a parallel node and has two regions :r1 and :r2, then it would be represented as [:s1 {:s1.1 {:r1 :r1-state :r2 :r2-state}}] ``` -------------------------------- ### Clojure State Machine Internal and External Self-Transitions Source: https://github.com/lucywang000/clj-statecharts/blob/master/docs/content/docs/transitions.md Details how to define self-transitions where a state transitions to itself. It distinguishes between internal self-transitions (omitting `:target`, not executing entry/exit actions) and external self-transitions (explicitly targeting itself, executing entry/exit actions). ```clojure {:states {:s1 {:entry entry1 :exit exit1 :on {:event1_1_internal {:actions some-action} ;; (1) :event1_1_external :s1 ;; (2) }}}} ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.