-
Notifications
You must be signed in to change notification settings - Fork 0
feature: dynamic signals 1 #9
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
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…lection_signal.test.ts`. - this will contain collection type signals, which will be dynamic in nature (i.e. have the ability to add and remove dependencies dynamically). - for now, only one kind of dynamic collection is implemented: the `UnisetStateSignal`, which will be able to hold a dynamic set-collection of other signal accessors. - the criteria for this signal to fire an update is as follows: - fire independently (i.e. as a source node in the DAG) when new accessors are added via its `addItems` method. - fire independently when existing accessors in the collection are deleted via its `delItems` method. - continue the propagation of a fired signal from one or more dependencies (regular signal DAG behavior). no equality check is performed, since the same set is used for updating the `this.value` of the UnisetStateSignal.
the new pattern looks more feasible, as it: - separates the logic between: - when the signal is to be fired independently due to a mutation in the underlying data structure that is carrying the collection of `Accessor`s. (this is what the `Uniset` class does) - when the signal needs to be fired as a result of one of its dependencies changing. (this is what the `UnisetSignal` class does) - moreover, it allows us to extend the data-structure which we wish to remix directly. thus allowing us to override super class methods, and also call `super` methods. it becomes far more clear this way which methods result in a potential mutation and will need to initiate the firing of an update cycle. - finally, in the `static create` method of the signal, it allows us to simply return the entire proxy-like data structure as a single item, rather than returning an array of bound closure methods. the advantage of this is that data structures with a ton of mutation methods (like `Array`s, with `push`, `pop`, `shift`, etc...) will not need to have all of their methods first bound, and then returned somewhere in a very long array of bound methods. it is simply unsustainable. - update the complementary test file to use the new signature of the `static create` signal method.
…ctionSignal` return class), that can be extended to adapt to any collection like signal. - make `UnisetSignal` extend `CollectionSignal`. - rename the `item` member in `UnisetSignal` to `data`. - change the fields needed in `BoundSignalInfo`. now it uses the `ctx: Context` as is, instead of using its individual member functions. it might have very minor performance and minifiablility implications, but it allows the proxy-like accessor collection data structures to use anything available by the context.
…ists (capable of in-between deletion and insertion). - implement an `RcList` that reference counts the multiplicity (amount of duplicates) of each unique element inside of the list array. this class is needed by a list-style collection signal, so that it can know when the dependency on a certain child-accessor has ended, so that it can delete the gaph edge. on the other hand, it will also allow us to seamlessly register new dependencies (when their reference counting (`rc`) comes up as 0).
this signal holds an array-like collection of `Accessor` signals, and takes care of reference counting to deallocate (remove dependency) former accessor elements that are no longer present anywhere in the array. - change the naming convention of base data structures that are promoted into signals, to contain a "Collection" appended to their name. - so, by this convention, the previous `Uniset` class is now called `UnisetCollection`. - and the newly introduced `RcList` based data structure is called `ListCollection`. - in the `List` class: - add methods for: `swap`ing elements, and `map`ing and `flatMap`ing to an `Array`. - fix a bug in the `insert` method which resulted in wrong indexing of the inserted item when using negative indices. previously: `list.insert(-1, item)` would place the `item` in the second to last element. but now: `list.insert(-1, item)` will correctly place it in the last spot (similar to pushing). - in `RcList`, fix a bug (formerly intentional) where reference counting is incremented before pushing/unshifting. now, it is the other way around (pushing comes first, then reference counting is incremented), in order to: - stay consistent with the remaining method's order of actions taken. - allows us to overload the `incRcs` method in subclass, knowing that the item _has_ been added already. this design makes it far more easier for the `ListCollection` subclass to react (fire an update cycle), with the most up to date array information (i.e. the update contains the newly added elements. but it wouldn't have if the actions taken were in reverse order, similar to the old way). - add a test file `/test/collections_signal.list.test.ts` to test the newly added `ListSignal`. - rename the test file `/test/collections_signal.test.ts` to `/test/collections_signal.uniset.test.ts`, since it is only intended to test the `UnisetSignal` signal class.
Sugoii!! |
omar-azmi
added a commit
that referenced
this pull request
Jun 17, 2024
other changes: - export the newly added dynamic collection signals #9 in `/src/collection_signal.ts`, to `/src/mod.ts` and `/deno.json`. - in `/readme.md`, fix a missing directed edge arrow (F -> I) in the mermaid diagram. this was pointed out to me by Abu.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
description:
This PR introduces two dynamic signals that hold a collection of
Accessor
s:UnisetSignal
: holds a set of accessors (Set<Accessor<T>>
), and when its value is requested, it returns the values of the accessors it is holding (as aSet<T>
).ListSignal
: holds an array of accessors (RcList<Accessor<T>>
), and when its value is requested, it returns an array of the values of the accessors it is holding (as aList<T>
).List
data structure is just your plain oldArray
with the addition of a few useful methods (insert
,delete
,swap
) that make it similar to python-style lists.In addition, it requires that you assign elemets using the
list.set(index, value)
method, instead of the index based assignmentlist[index] = value
. This is so that its subclasses can keep track of what assignments are taking place (without having to resort to nasty proxies).RcList
is a subclass of theList
class, but it reference counts the elements that are added or removed from it.This feature is necessary for its signal compatible subclass
ListCollection
to be able to dynamically tell whichAccessor
s the signal is dependant on, and which of them are being dynamically removed completely (with no duplicates remaining) to de-allocate its dependency on them.This PR builds on the
Identifiable
signal feature introduced in #8 , which simplifies the ability to tell the signalid
of a signal jsut from itsAccessor
.justification:
Previously, basic dynamic collection based tasks were incredibly difficult to implement, and needed to be tailored to the specific datatype structure that was being held in a collection.
This is because the library formerly focused additive signals, where, by design, new signals that were created built themselves over static-and-existing older signals.
This made sense dependency-wise, because a
Memo
function would always carry the same set of dependencies.But as a consequence, implementing basic collection-based dynamic signal, such as that of a "To-Do list" (i.e. an
Accessor<Array<Accessor<TodoInterface>>>
), was incredibly dificult.With this PR, dynamic signals based on
Set
s orArray
s become easy to implement using the library providedUnisetSignal_Factory
andListSignal_Factory
exports.future:
In the future, I hope to add two more dynamic collections (in the
feature/dynamic-signals-2
branch):MapCollection<K, V extends Accessor<any>>
and its complementaryMapSignal<K, V extends Accessor<any>>
for holdingAccessor
s in aMap
based datastructure.ObjectCollection<SCHEMA>
and its complementaryObjectSignal<SCHEMA>
, whereSCHEMA
is an interface with anykey: K extends PropertyKey
, andvalue: V extends Accessor<any>
pairs.