feat(atom): add dedupeWith combinator for custom write equivalence#415
Open
front-depiction wants to merge 1 commit intotim-smart:mainfrom
Open
feat(atom): add dedupeWith combinator for custom write equivalence#415front-depiction wants to merge 1 commit intotim-smart:mainfrom
front-depiction wants to merge 1 commit intotim-smart:mainfrom
Conversation
Every atom already deduplicates writes via Equal.equals, but that falls back to reference equality for plain objects/arrays — causing re-notifies on structurally-equal new references. dedupeWith lets callers attach a custom Equivalence so structurally-equal writes become no-ops. The default is preserved exactly: AtomProto carries eq = Equal.equals, so existing atoms see no behavior change.
29b0c27 to
a0b7ff4
Compare
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
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.
Summary
Every atom already deduplicates writes using
Equal.equals(Node.setValueininternal/registry.ts), butEqual.equalsfalls back to reference equality for values that don't implementEqual— plain objects, arrays, API payloads, derived collections. A structurally-identical new reference therefore re-notifies every subscriber and cascades invalidation downstream. This combinator sits in between no equality, and implementing custom Equal.Equal traits.dedupeWithattaches a customEquivalence<A>to an atom so structurally-equal writes become no-ops.Design
Atom<A>gainsreadonly eq: Equivalence<A>, defaulted viaAtomPrototoEqual.equals. No branching in the hot path —this.atom.eq(prev, next)is always a function call.dedupeWithis dual (data-first / data-last), returnsSelf → Self, and clones the prototype the same waysetIdleTTLdoes (Object.assign(Object.create(proto), { ...self, eq })), preservingWritable/AtomRuntimeproto methods.Node.setValuechanges one line:Equal.equals(this._value, value)→this.atom.eq(this._value, value).dedupeWithcall continue to dedupe viaEqual.equals.Test plan
New
describe("dedupeWith")block inpackages/atom/test/Atom.test.tscovers:dedupeWithre-notifies on structurally-equal new references (status-quo witness)dedupeWithwith a custom equivalence suppresses notify on structurally-equal writes and fires on genuinely new valuesdedupeWithdoes not suppress the initial valuesetIdleTTLin either order (botheqandidleTTLpreserved)Full suite: 104/104 pass.
pnpm lint,pnpm circular,pnpm docgenclean. Changeset added (@effect-atom/atom: minor).