Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Dangerous experiments with subatomic particles.

License

NotificationsYou must be signed in to change notification settings

microstates/lab

Repository files navigation

License: MITCreated by The FrontsideBuild StatusCoverage StatusGreenkeeper badge

❤ @microstate/lab ❤️

Dangerous experiments with subatomic particles.

Linked Microstates

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.

Ownership of microstates

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();}

What it enables.

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
Table

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

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors3

  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp