Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hierarchical POC #73

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open

Hierarchical POC #73

wants to merge 5 commits into from

Conversation

devanshj
Copy link
Contributor

@devanshj devanshj commented Aug 4, 2021

Just a little poc I tried (not very tested), wanted to keep it fp let me know if you like it so either of us can take this forward!

I know this is the least important thing right now as it's for 1.2.0 but as usual I was bored and wanted to do something fun xD

(I have based it on api-change-for-sendt as you haven't merged it yet)

Edit, A gist how it works:

We store the state of the machine in form of a tree. Where each node can be thought of a stateful submachine. Each node has children and state which is the identifier of the active child.

So the final "state" ie an sequential array from outermost active node to innermost active node is derived via Node.state and is not the source of truth. (Might rename the property state of node to be something else because node.state and Node.state(node) read similar but are completely different)

So essentially when an event comes we find out the nextStateIdentifier, then compute the nextState from it, then diff it with the currentState for entries and exits.

So for the test case something like this happens...

got event X
resolved nextStateIdentifier to a2
derived nextState to be [a, a2]
derived currentState to be [b, b1]
Diffed them to compute entries to be [a, a2] and exits to be [b, b1]
Run effect cleanups for exits in reverse order
Run effects for entries

The Node.transition part is completely pure (it gives [newNode, entries, exits]) so it will help with testing (I'm thinking of some snapshot based testing) and also with shouldSend as we could simply send it and see if the state changes.

machine = { ...machineInstant, send }
Machine.State -> Machine
machineState -> machineInstant
machineState.value -> machineInstant.state
Machine.StateValue -> Machine.State
@cassiozen
Copy link
Owner

cassiozen commented Aug 4, 2021

You are a machine. This is awesome! Checking the code right now.

We store the state of the machine in form of a tree. Where each node can be thought of a stateful submachine. Each node has children and state which is the identifier of the active child.

So the final "state" ie an sequential array from outermost active node to innermost active node is derived via Node.state and is not the source of truth.

Correct. Are we also representing the state as a array in case of a flat, single-level state machine?

(Might rename the property state of node to be something else because node.state and Node.state(node) read similar but are completely different)

Yeah, makes sense.

So essentially when an event comes we find out the nextStateIdentifier, then compute the nextState from it, then diff it with the currentState for entries and exits.

Yeah, we might need to use a pathfinding algorithm (opposed to just traversing the tree until we find the nodes).

So for the test case something like this happens...
got event X
resolved nextStateIdentifier to a2
derived nextState to be [a, a2]
derived currentState to be [b, b1]
Diffed them to compute entries to be [a, a2] and exits to be [a, a2]
Run effect cleanups for exits in reverse order
Run effects for entries

Correct, assuming you meant that exist would be [b, b1]

@devanshj
Copy link
Contributor Author

devanshj commented Aug 4, 2021

You are a machine. This is awesome!

Hahaha thanks a lot!

Are we also representing the state as a array in case of a flat, single-level state machine?

Yep Node.state always returns an array for all kinds of machines.

Yeah, we might need to use a pathfinding algorithm (opposed to just traversing the tree until we find the nodes)

How would the pathfinding algorithm work without traversing the tree though? This version does a depth-first search (assuming nextState would be the one that does what you're talking about). We could memoize it, as it's stateless ie does not depend on the state of the node or the machine.

Correct, assuming you meant that exist would be [b, b1]

Right, typo (will edit for posterity)

node.state ->node.current
node.initialState -> node.initial
Node.nextStateFromNextStateIdentifier -> Node.nextState
Node.entriesAndExitsForEvent -> node.entriesAndExits
@cassiozen
Copy link
Owner

How would the pathfinding algorithm work without traversing the tree though? This version does a depth-first search (assuming nextState would be the one that does what you're talking about). We could memoize it, as it's stateless ie does not depend on the state of the node or the machine.

We could traverse from the nodes and find the shortest path without necessarily traversing the whole tree from the top - but thinking about it, it seems like a premature optimization - Most likely the state tree won't be complex or big enough to benefit from this...

@devanshj
Copy link
Contributor Author

devanshj commented Aug 5, 2021

We could traverse from the nodes and find the shortest path without necessarily traversing the whole tree from the top

Huh? xD I don't follow, wym by "find the shortest path"? To make sure we're on the same page we're taking about an algorithm that takes an input rootNode and "a1" and gives output ["a", "a1"].

EDIT: Oh wait we have an additional information that the current state is b.b1 so we could start looking for nodes with identifier a1 starting from there, perhaps that's what you meant by "shortest path" -- makes sense.

but thinking about it, it seems like a premature optimization - Most likely the state tree won't be complex or big enough to benefit from this...

Yep exactly, but I think it's a good improvement nonetheless.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants