- Notifications
You must be signed in to change notification settings - Fork0
Dangerous experiments with subatomic particles.
License
microstates/lab
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Dangerous experiments with subatomic particles.
In this lab experiment, we're seeking to enable linking from one partof the microstate graph to acompletely separate part. This willallows us to do things, like share a store between multiple instancesof a microstate. Seehttps://beta.observablehq.com/@cowboyd/microstate-variables for astatement of the problem.
The approach is to make microstates pass around the entireatom inwhich they are participating every time, and then treat themselves notas a Type and a value, but rather as aType and a pointer into theatom. That way, if a graph of microstates all share the same atom,then they can reference other microstates with only a Type and a path intothat atom. Transitions on the linked microstate will happen at thatlocation in the atom (wherever in the atom that location happens tobe). Because all operations anywhere in the graph happen on the atom,then they will be immediately visible to operations.
Let's see some concrete examples to see what that means. We won't useany new functionality that this scheme enables, only existingfunctionality. That way we can see the difference in representation.
the example of anApp which contains aPopup. The popup has acounter that it uses to track internally how many times it has been shown.
classApp{popup=Popup;}classPopup{isOpen=Boolean;count=Number;show(){returnthis.isOpen.set(true).count.increment();}}
In the old way, each microstate kept a reference to its very ownvalue:
letapp=create(App,{popup:{isOpen:false,count:0}});metaOf(app).value//=> {popup: { isOpen: false, count: 0}}metaOf(app.popup).value//=> { isOpen: false, count: 0 };metaOf(app.popup.count).value//=> 0;
In the new way, notice how theapp andapp.popup, andapp.popup.count all share theexact same atom
letapp=create(App,{popup:{isOpen:false,count:0}});metaOf(app).atom//=> {popup: { isOpen: false, count: 0}}metaOf(app.popup).atom//=> {popup: { isOpen: false, count: 0}}metaOf(app.popup.count).atom//=> {popup: { isOpen: false, count: 0}}
The way they achieve a unique value is to lookup their path withinthe atom.
valueOf(app.popup.count)//=> 0
That way, value lookup works as expected.
Before, every transition started effectively at its own root ofthe tree. (the transition context was a microstate of the type usedcreated from scratch). Now, there is a problem of where to mark theboundary of a transition, or What is thereturn value of atransition.
As we can see from our classPopup, there are a couple placeswhere even though the transition is on a substate, it returns aninstance ofPopup. Which type and path to return is known in thisexperiment as "ownership". Every microstate has an owner, where theowner is theType +path of the parent microstate in which itappears, and the target for which transitions should resolve to.
A microstatecan be its own owner.
As you can see, all of the objects you reach from theapp objecthave the same owner
ownerOf(app)//> { Type: App, path: [] }locationOf(app)//> { Type: App, path: [] }ownerOf(app.popup)//=> { Type: App, path: [] }locationOf(app.popup)//=> { Type: Popup, path: ['popup'] }ownerOf(app.popup.count)//=> { Type: App, path: [] }locationOf(app.popup.count)//=> { Type: Number, path: ['popup', 'count'] }
That means that any transition invoked by any of these objects willresult in anApp object that points to path[] in the resultingatom.
By contrast, within theshow() transition of the popup, the ownerwill have shifted down to be thePopup. But notice that the locationis still an absolute path within the total atom and not a relative path.
show(){ownerOf(this)//=> { Type: Popup, path: ['popup']}locationOf(this)//=> { Type: Popup, path: ['popup']}ownerOf(this.isOpen)//=> { Type: Popup, path: ['popup']}locationOf(this.isOpen)//=> { Type: Boolean, path: ['popup', 'isOpen']}ownerOf(this.count)//=> { Type: Popup, path: ['popup']}locationOf(this.count)//=> { Type: Number, path: ['popup', count']}returnthis.isOpen.set(true).count.increment();}
Since a microstate can point toanywhere in the atom, and it can beowned by any microstate, this lets us embed any microstate pointingto anywhere that can be owned by anything. So, for example, imagine wehave as part of our application a list of layers for a popup thatlived at the path ['rendering', 'stack', 'layers']. We could create apopup that linked to this location even though the ['popup'] is not adescendant of this path.
Now, we can have alayers property that isownned by the popup,but islocated outside:
classPopup{show(){ownerOf(this.layers)//=> { Type: Popup, path: ['popup'] }locationOf(this.layers)//=> { Type: LayerStack, path: ['rendering', 'stack', 'layers']}returnthis.layers.allocate().isOpen.set(true).count.increment();}}
The mechanism to declare this is still a work in progress, but thetest cases inlab.test.js have a proof of concept in which one handclaps the other.
// clap transition on hand look like this. It claps itself, and then// claps the other. (other will be a link to the other hand)clap(){returnthis.other.claps.increment().claps.increment()}// a person has a left hand and a right hand:letperson=create(Person,{left:{claps:1},right:{claps:1}});letclapped=person.right.clap();// we clapped the right hand, but the left count incremented too.clapped.left.claps.state//=> 2
Using the ability to "link into" a data structure anywhere inside theatom, we can use this to implement one of the holy grails of datastructures: aTable
The cells are just a lazy enumeration that returns the cell type ofthe table. The rows are a lazy enumeration of rows, that lazilyenumerate cells of the same type within the table. And, notsuprisingly, the columns are a lazy enumeration of column objects thatlazily enumerate the cells in that column.
See thetestcases for example usage.
About
Dangerous experiments with subatomic particles.
Resources
License
Code of conduct
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Contributors3
Uh oh!
There was an error while loading.Please reload this page.