Lucy: A concise language for describing Finite State Machines
pkg.spooky.click
pkg.spooky.click
[1]: https://astro.build/
Also ultimately it was hard to sell the idea of living in a different file format from the rest of your code. This is always a tough sell for DSLs. Even languages as good as CSS and SQL struggle with this for a lot of devs.
Instead of conforming to an XML specification created decades ago, Robot takes the best ideas from both academia and real-world usage of finite state machines. This makes state machines easy to read and understand, as there is only one way to do most common tasks.
...is hinting at some disagreements with XState's approach. Would be nice to have a visualization tool, like the kind XState has, for any FSM library (like robot) though.[0]: https://www.w3.org/TR/scxml/
[1]: https://stately.ai/docs/xstate-v4/xstate/advanced/scxml
Alternatively, a regular language can be defined as a language recognised by a finite automaton. The equivalence of regular expressions and finite automata is known as Kleene's theorem
I think a cool state machine language would use this fact as a starting point for it's syntax. Another very useful feature would be "functions" to isolate specific repetitive parts of FSMBy the way regular expressions are "composable" by definition as they are defined recursively as (in their simplest form)
- ε is the regex that matches the empty string
- given regexes A and B we can construct the new regex AB that matches first the regex A followed by B
- given regexes A and B we can construct A|B that matches A or B
- given a regex A the regex A* matches any number of repeated occurrences of A
Then for some reason languages like javascript don't provide a way of constructing
/foo/.concat(/bar/) // equivalent to /foobar/
but that is another problem.Concatenation and alternation is not what one typically imagines when they utter the word composition (unless you expect me to understand "composition over inheritance" to mean actually "just use two classes instead of one").
I'm curious. What came to your mind for "composition"?
> probably had functional programming in mind
Then you should have no trouble recognizing that there is no analog to `f . g . h` for regexes.
FOMA [1] is an open source clone of the Xerox XFST tools [2,3] developed at Xerox Research Laboratory Europe in Grenoble under the late Prof. Lauri Karttunen.
While the FOMA/XFST family of tools are most suitable for linguistic applications and for teaching formal language theory, I have been impressed by the fact that they are the only formalism that permits elegant naming and re-use of sub-automata.
[1] https://fomafst.github.io/
[2] https://citeseerx.ist.psu.edu/document?repid=rep1&type=pdf&d...
"Classic state diagrams require the creation of distinct nodes for every valid combination of parameters. For all but the simplest of systems, this can lead to a very large number of nodes and transitions between nodes (state and transition explosion), which reduces the readability of the state diagram." [1]
"What's missing in the traditional state machines is the mechanism for factoring out the common behavior in order to share it across many states. UML state machines address exactly this shortcoming of the conventional FSMs. They provide a number of features for eliminating the repetitions so that the complexity of a UML state machine no longer explodes..." [2]
--
1: https://en.wikipedia.org/wiki/State_diagram#Harel_statechart
2: https://en.wikipedia.org/wiki/UML_state_machine#UML_extensio...
(defmodule avoid
:inputs (force heading)
:outputs (command)
:instance-vars (resultforce)
:states ((nil (event-dispatch (and force heading) plan))
(plan (setf resultforce (select-direction force heading))
go)
(go (conditional-dispatch (significant-force-p resultforce 1.0)
start
nil))
(start (output command (follow-force resultforce))
nil)))
[0] https://www.semanticscholar.org/paper/A-robust-layered-contr... public interface TurnstileState {}
public interface LockedState extends TurnstileState {}
public class UnlockedState implements TurnstileState {
public final int credits;
public UnlockedState(int credits) {
this.credits = credits;
}
}
public static final LockedState LOCKED = new LockedState() {};
StateMachine<TurnstileState> turnstile = StateMachine.<TurnstileState>.newBuilder()
.addValidTransition(LockedState.class, UnlockedState.class)
.addValidTransition(UnlockedState.class, LockedState.class)
.addValidTransition(UnlockedState.class, UnlockedState.class)
.buildWithInitialState(LOCKED);
turnstile.transition(new UnlockedState(1));
I never got around to building out examples in Kotlin. I feel like the type checking there would streamline a ton of this even further.https://github.com/Hounshell/st8 if anyone wants to see the gory bits.
Hasn't been updated in 4 years, and is now archived, so I assume this project is dead. Looks good though!