-
-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(defmulti): split into separate files
- Loading branch information
1 parent
cff9e30
commit dae6009
Showing
5 changed files
with
624 additions
and
606 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,305 @@ | ||
import { | ||
Fn, | ||
Fn2, | ||
Fn3, | ||
Fn4, | ||
Fn5, | ||
Fn6, | ||
Fn7, | ||
Fn8, | ||
FnAny, | ||
IObjectOf | ||
} from "@thi.ng/api"; | ||
|
||
export const DEFAULT: unique symbol = Symbol(); | ||
|
||
export type DispatchFn = FnAny<PropertyKey>; | ||
export type DispatchFn1<A> = Fn<A, PropertyKey>; | ||
export type DispatchFn1O<A, B> = (a: A, b?: B) => PropertyKey; | ||
export type DispatchFn2<A, B> = Fn2<A, B, PropertyKey>; | ||
export type DispatchFn2O<A, B, C> = (a: A, b: B, c?: C) => PropertyKey; | ||
export type DispatchFn3<A, B, C> = Fn3<A, B, C, PropertyKey>; | ||
export type DispatchFn3O<A, B, C, D> = (a: A, b: B, c: C, d?: D) => PropertyKey; | ||
export type DispatchFn4<A, B, C, D> = Fn4<A, B, C, D, PropertyKey>; | ||
export type DispatchFn4O<A, B, C, D, E> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e?: E | ||
) => PropertyKey; | ||
export type DispatchFn5<A, B, C, D, E> = Fn5<A, B, C, D, E, PropertyKey>; | ||
export type DispatchFn5O<A, B, C, D, E, F> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f?: F | ||
) => PropertyKey; | ||
export type DispatchFn6<A, B, C, D, E, F> = Fn6<A, B, C, D, E, F, PropertyKey>; | ||
export type DispatchFn6O<A, B, C, D, E, F, G> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g?: G | ||
) => PropertyKey; | ||
export type DispatchFn7<A, B, C, D, E, F, G> = Fn7< | ||
A, | ||
B, | ||
C, | ||
D, | ||
E, | ||
F, | ||
G, | ||
PropertyKey | ||
>; | ||
export type DispatchFn7O<A, B, C, D, E, F, G, H> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g: G, | ||
h?: H | ||
) => PropertyKey; | ||
export type DispatchFn8<A, B, C, D, E, F, G, H> = Fn8< | ||
A, | ||
B, | ||
C, | ||
D, | ||
E, | ||
F, | ||
G, | ||
H, | ||
PropertyKey | ||
>; | ||
export type DispatchFn8O<A, B, C, D, E, F, G, H, I> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g: G, | ||
h: H, | ||
i?: I | ||
) => PropertyKey; | ||
|
||
export type Implementation<T> = FnAny<T>; | ||
export type Implementation1<A, T> = Fn<A, T>; | ||
export type Implementation1O<A, B, T> = (a: A, b?: B) => T; | ||
export type Implementation2<A, B, T> = Fn2<A, B, T>; | ||
export type Implementation2O<A, B, C, T> = (a: A, b: B, c?: C) => T; | ||
export type Implementation3<A, B, C, T> = Fn3<A, B, C, T>; | ||
export type Implementation3O<A, B, C, D, T> = (a: A, b: B, c: C, d?: D) => T; | ||
export type Implementation4<A, B, C, D, T> = Fn4<A, B, C, D, T>; | ||
export type Implementation4O<A, B, C, D, E, T> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e?: E | ||
) => T; | ||
export type Implementation5<A, B, C, D, E, T> = Fn5<A, B, C, D, E, T>; | ||
export type Implementation5O<A, B, C, D, E, F, T> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f?: F | ||
) => T; | ||
export type Implementation6<A, B, C, D, E, F, T> = Fn6<A, B, C, D, E, F, T>; | ||
export type Implementation6O<A, B, C, D, E, F, G, T> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g?: G | ||
) => T; | ||
export type Implementation7<A, B, C, D, E, F, G, T> = Fn7< | ||
A, | ||
B, | ||
C, | ||
D, | ||
E, | ||
F, | ||
G, | ||
T | ||
>; | ||
export type Implementation7O<A, B, C, D, E, F, G, H, T> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g: G, | ||
h?: H | ||
) => T; | ||
export type Implementation8<A, B, C, D, E, F, G, H, T> = Fn8< | ||
A, | ||
B, | ||
C, | ||
D, | ||
E, | ||
F, | ||
G, | ||
H, | ||
T | ||
>; | ||
export type Implementation8O<A, B, C, D, E, F, G, H, I, T> = ( | ||
a: A, | ||
b: B, | ||
c: C, | ||
d: D, | ||
e: E, | ||
f: F, | ||
g: G, | ||
h: H, | ||
i?: I | ||
) => T; | ||
|
||
export interface MultiFnBase<I> { | ||
/** | ||
* Registers implementation for dispatch value `id`. Returns true, | ||
* if successful. Returns false if an implementation already exists | ||
* (and does nothing in this case). | ||
* | ||
* @param id | ||
* @param impl | ||
*/ | ||
add(id: PropertyKey, impl: I): boolean; | ||
/** | ||
* Takes an object of dispatch values and their implementations and | ||
* calls `.add()` for each KV pair. Returns true, if all impls were | ||
* added successfully. Note: Only numbers or strings are accepted as | ||
* dispatch values here. | ||
* | ||
* @param impls | ||
*/ | ||
addAll(impls: IObjectOf<I>): boolean; | ||
/** | ||
* Removes implementation for dispatch value `id`. Returns true, if | ||
* successful. | ||
* | ||
* @param id | ||
*/ | ||
remove(id: PropertyKey): boolean; | ||
/** | ||
* Returns true, if the function is callable (has a valid | ||
* implementation) for given arguments. | ||
* | ||
* @param args | ||
*/ | ||
callable(...args: any[]): boolean; | ||
/** | ||
* Returns a set of all registered dispatch values. | ||
*/ | ||
impls(): Set<PropertyKey>; | ||
/** | ||
* Updates dispatch hierarchy by declaring dispatch value `id` to | ||
* delegate to `parent`'s implementation. I.e. in terms of dispatch | ||
* logic, `id` is considered the same as `parent. | ||
* | ||
* @param id | ||
* @param parent | ||
*/ | ||
isa(id: PropertyKey, parent: PropertyKey): boolean; | ||
/** | ||
* Returns all known dispatch relationships. This is an object with | ||
* all registered dispatch values as keys, each with a set of parent | ||
* dispatch values. | ||
*/ | ||
rels(): IObjectOf<Set<PropertyKey>>; | ||
/** | ||
* Returns a set of immediate parent dispatch values for given | ||
* dispatch value `id`. | ||
* | ||
* @param id | ||
*/ | ||
parents(id: PropertyKey): Set<PropertyKey>; | ||
/** | ||
* Similar to `parents()`, but includes all transitive parent dispatch | ||
* values for given dispatch value `id`. | ||
* @param id | ||
*/ | ||
ancestors(id: PropertyKey): Set<PropertyKey>; | ||
} | ||
|
||
export interface MultiFn<T> | ||
extends Implementation<T>, | ||
MultiFnBase<Implementation<T>> {} | ||
|
||
export interface MultiFn1<A, T> | ||
extends Implementation1<A, T>, | ||
MultiFnBase<Implementation1<A, T>> {} | ||
|
||
export interface MultiFn1O<A, B, T> | ||
extends Implementation1O<A, B, T>, | ||
MultiFnBase<Implementation1O<A, B, T>> {} | ||
|
||
export interface MultiFn2<A, B, T> | ||
extends Implementation2<A, B, T>, | ||
MultiFnBase<Implementation2<A, B, T>> {} | ||
|
||
export interface MultiFn2O<A, B, C, T> | ||
extends Implementation2O<A, B, C, T>, | ||
MultiFnBase<Implementation2O<A, B, C, T>> {} | ||
|
||
export interface MultiFn3<A, B, C, T> | ||
extends Implementation3<A, B, C, T>, | ||
MultiFnBase<Implementation3<A, B, C, T>> {} | ||
|
||
export interface MultiFn3O<A, B, C, D, T> | ||
extends Implementation3O<A, B, C, D, T>, | ||
MultiFnBase<Implementation3O<A, B, C, D, T>> {} | ||
|
||
export interface MultiFn4<A, B, C, D, T> | ||
extends Implementation4<A, B, C, D, T>, | ||
MultiFnBase<Implementation4<A, B, C, D, T>> {} | ||
|
||
export interface MultiFn4O<A, B, C, D, E, T> | ||
extends Implementation4O<A, B, C, D, E, T>, | ||
MultiFnBase<Implementation4O<A, B, C, D, E, T>> {} | ||
|
||
export interface MultiFn5<A, B, C, D, E, T> | ||
extends Implementation5<A, B, C, D, E, T>, | ||
MultiFnBase<Implementation5<A, B, C, D, E, T>> {} | ||
|
||
export interface MultiFn5O<A, B, C, D, E, F, T> | ||
extends Implementation5O<A, B, C, D, E, F, T>, | ||
MultiFnBase<Implementation5O<A, B, C, D, E, F, T>> {} | ||
|
||
export interface MultiFn6<A, B, C, D, E, F, T> | ||
extends Implementation6<A, B, C, D, E, F, T>, | ||
MultiFnBase<Implementation6<A, B, C, D, E, F, T>> {} | ||
|
||
export interface MultiFn6O<A, B, C, D, E, F, G, T> | ||
extends Implementation6O<A, B, C, D, E, F, G, T>, | ||
MultiFnBase<Implementation6O<A, B, C, D, E, F, G, T>> {} | ||
|
||
export interface MultiFn7<A, B, C, D, E, F, G, T> | ||
extends Implementation7<A, B, C, D, E, F, G, T>, | ||
MultiFnBase<Implementation7<A, B, C, D, E, F, G, T>> {} | ||
|
||
export interface MultiFn7O<A, B, C, D, E, F, G, H, T> | ||
extends Implementation7O<A, B, C, D, E, F, G, H, T>, | ||
MultiFnBase<Implementation7O<A, B, C, D, E, F, G, H, T>> {} | ||
|
||
export interface MultiFn8<A, B, C, D, E, F, G, H, T> | ||
extends Implementation8<A, B, C, D, E, F, G, H, T>, | ||
MultiFnBase<Implementation8<A, B, C, D, E, F, G, H, T>> {} | ||
|
||
export interface MultiFn8O<A, B, C, D, E, F, G, H, I, T> | ||
extends Implementation8O<A, B, C, D, E, F, G, H, I, T>, | ||
MultiFnBase<Implementation8O<A, B, C, D, E, F, G, H, I, T>> {} | ||
|
||
export type AncestorDefs = IObjectOf<Iterable<PropertyKey>>; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { illegalArity } from "@thi.ng/errors"; | ||
import { DEFAULT, Implementation } from "./api"; | ||
import { defmulti } from "./defmulti"; | ||
|
||
/** | ||
* Returns a multi-dispatch function which delegates to one of the | ||
* provided implementations, based on the arity (number of args) when | ||
* the function is called. Internally uses `defmulti`, so new arities | ||
* can be dynamically added (or removed) at a later time. If no | ||
* `fallback` is provided, `defmultiN` also registers a `DEFAULT` | ||
* implementation which simply throws an `IllegalArityError` when | ||
* invoked. | ||
* | ||
* **Note:** Unlike `defmulti` no argument type checking is supported, | ||
* however you can specify the return type for the generated function. | ||
* | ||
* ``` | ||
* const foo = defmultiN<string>({ | ||
* 0: () => "zero", | ||
* 1: (x) => `one: ${x}`, | ||
* 3: (x, y, z) => `three: ${x}, ${y}, ${z}` | ||
* }); | ||
* | ||
* foo(); | ||
* // zero | ||
* foo(23); | ||
* // one: 23 | ||
* foo(1, 2, 3); | ||
* // three: 1, 2, 3 | ||
* foo(1, 2); | ||
* // Error: illegal arity: 2 | ||
* | ||
* foo.add(2, (x, y) => `two: ${x}, ${y}`); | ||
* foo(1, 2); | ||
* // two: 1, 2 | ||
* ``` | ||
* | ||
* @param impls | ||
* @param fallback | ||
*/ | ||
export const defmultiN = <T>( | ||
impls: { [id: number]: Implementation<T> }, | ||
fallback?: Implementation<T> | ||
) => { | ||
const fn = defmulti<T>((...args: any[]) => args.length); | ||
fn.add(DEFAULT, fallback || ((...args) => illegalArity(args.length))); | ||
for (let id in impls) { | ||
fn.add(id, impls[id]); | ||
} | ||
return fn; | ||
}; |
Oops, something went wrong.