Closed pebell closed 6 years ago
A very good idea, and should be part of our roadmap.
Equality functions are not only used for Atoms, but also for derivations and reactors. When a derivation is recalculated, the new value should be compared to the old value using the "pluggable" equals
function. This is part of the algorithm that ensures that the absolute minimum of work is done while at the same time ensuring reactors that need to fire are fired.
I see several solutions that we need to investigate and perhaps implement multiple versions.
Provide a way to configure a single atom or derivable during creation. This could look as follows:
import { atom, derivation } from '@politie/sherlock';
// Normal use:
const a$ = atom('some value');
const d$ = derivation(() => a$.get() + '!');
// Use a custom equals function that only compares lengths:
function myEquals(a: string, b: string) { return a.length === b.length; }
const b$ = atom({ equals: myEquals }, 'some other value');
const d$ = derivation({ equals: myEquals }, () => a$.get() + b$.get());
Provide a way to transform an atom or derivable with one equals function into an atom or derivable with another equals function as follows:
import { atom, derivation } from '@politie/sherlock';
// Normal use:
const a$ = atom('some value');
// Use a custom equals function that only compares lengths:
const b$ = a$.withEquals(myEquals);
// Or when used in a derivation:
const d$ = derivation(() => a$.get() + b$.get()).withEquals(myEquals);
Provide a way to configure a new "instance" of the entire Sherlock library where the equals
function is configured (and perhaps in the future other configs as well). This could work something like this:
// my-sherlock.ts
// A local file that configures Sherlock just the way you want it for your own
// project. In the rest of the project import all Sherlock primitives from here.
// Export all symbols from sherlock.
export * from '@politie/sherlock'
// But overwrite atom, lens and derivation to use our equals function.
import { createInstance } from '@politie/sherlock'
const { atom, derivation, lens } = createInstance({ equals: myEquals });
export { atom, derivation, lens };
Simply use a config object that configures Sherlock globally. This is what most other libraries do.
Let me know what you think.
The documentation on the
Atom
class states:The current implementation uses the
equals
method (if it exists) on the atom value to determine if a state change has occurred. This works out of the box with Facebooks Immutable.js because these objects expose anequals
method. But ordinary objects or objects created with for example seamless-immutable do not provide such anequals
method and are therefore less efficient to use with Sherlock.By allowing to initialize an Atom with a custom or "pluggable"
equals
function, one could create an Atom that works with all kind of data structures, not only objects with anequals
method.