@thi.ng/defmulti
Advanced tools
Comparing version 0.7.0 to 1.0.0
@@ -6,2 +6,31 @@ # Change Log | ||
# [1.0.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@0.7.0...@thi.ng/defmulti@1.0.0) (2019-01-21) | ||
### Build System | ||
* update package build scripts & outputs, imports in ~50 packages ([b54b703](https://github.com/thi-ng/umbrella/commit/b54b703)) | ||
### Features | ||
* **defmulti:** add callable() & implementations(), update readme ([fde2db2](https://github.com/thi-ng/umbrella/commit/fde2db2)) | ||
* **defmulti:** add relations() ([4066c80](https://github.com/thi-ng/umbrella/commit/4066c80)) | ||
* **defmulti:** add versions w/ 1 optional typed arg, add .impls() ([125c784](https://github.com/thi-ng/umbrella/commit/125c784)) | ||
### BREAKING CHANGES | ||
* enabled multi-outputs (ES6 modules, CJS, UMD) | ||
- build scripts now first build ES6 modules in package root, then call | ||
`scripts/bundle-module` to build minified CJS & UMD bundles in `/lib` | ||
- all imports MUST be updated to only refer to package level | ||
(not individual files anymore). tree shaking in user land will get rid of | ||
all unused imported symbols. | ||
# [0.7.0](https://github.com/thi-ng/umbrella/compare/@thi.ng/defmulti@0.6.0...@thi.ng/defmulti@0.7.0) (2019-01-02) | ||
@@ -8,0 +37,0 @@ |
144
index.d.ts
@@ -1,21 +0,37 @@ | ||
import { IObjectOf } from "@thi.ng/api/api"; | ||
import { IObjectOf } from "@thi.ng/api"; | ||
export declare const DEFAULT: unique symbol; | ||
export declare type DispatchFn = (...args: any[]) => PropertyKey; | ||
export declare type DispatchFn1<A> = (a: A, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn2<A, B> = (a: A, b: B, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn3<A, B, C> = (a: A, b: B, c: C, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn4<A, B, C, D> = (a: A, b: B, c: C, d: D, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn5<A, B, C, D, E> = (a: A, b: B, c: C, d: D, e: E, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn6<A, B, C, D, E, F> = (a: A, b: B, c: C, d: D, e: E, f: F, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn7<A, B, C, D, E, F, G> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn8<A, B, C, D, E, F, G, H> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, ...xs: any[]) => PropertyKey; | ||
export declare type DispatchFn1<A> = (a: A) => PropertyKey; | ||
export declare type DispatchFn1O<A, B> = (a: A, b?: B) => PropertyKey; | ||
export declare type DispatchFn2<A, B> = (a: A, b: B) => PropertyKey; | ||
export declare type DispatchFn2O<A, B, C> = (a: A, b: B, c?: C) => PropertyKey; | ||
export declare type DispatchFn3<A, B, C> = (a: A, b: B, c: C) => PropertyKey; | ||
export declare type DispatchFn3O<A, B, C, D> = (a: A, b: B, c: C, d?: D) => PropertyKey; | ||
export declare type DispatchFn4<A, B, C, D> = (a: A, b: B, c: C, d: D) => PropertyKey; | ||
export declare type DispatchFn4O<A, B, C, D, E> = (a: A, b: B, c: C, d: D, e?: E) => PropertyKey; | ||
export declare type DispatchFn5<A, B, C, D, E> = (a: A, b: B, c: C, d: D, e: E) => PropertyKey; | ||
export declare type DispatchFn5O<A, B, C, D, E, F> = (a: A, b: B, c: C, d: D, e: E, f?: F) => PropertyKey; | ||
export declare type DispatchFn6<A, B, C, D, E, F> = (a: A, b: B, c: C, d: D, e: E, f: F) => PropertyKey; | ||
export declare 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 declare type DispatchFn7<A, B, C, D, E, F, G> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => PropertyKey; | ||
export declare 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 declare type DispatchFn8<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 declare 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 declare type Implementation<T> = (...args: any[]) => T; | ||
export declare type Implementation1<A, T> = (a: A, ...xs: any[]) => T; | ||
export declare type Implementation2<A, B, T> = (a: A, b: B, ...xs: any[]) => T; | ||
export declare type Implementation3<A, B, C, T> = (a: A, b: B, c: C, ...xs: any[]) => T; | ||
export declare type Implementation4<A, B, C, D, T> = (a: A, b: B, c: C, d: D, ...xs: any[]) => T; | ||
export declare type Implementation5<A, B, C, D, E, T> = (a: A, b: B, c: C, d: D, e: E, ...xs: any[]) => T; | ||
export declare type Implementation6<A, B, C, D, E, F, T> = (a: A, b: B, c: C, d: D, e: E, f: F, ...xs: any[]) => T; | ||
export declare type Implementation7<A, B, C, D, E, F, G, T> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G, ...xs: any[]) => T; | ||
export declare type Implementation8<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, ...xs: any[]) => T; | ||
export declare type Implementation1<A, T> = (a: A) => T; | ||
export declare type Implementation1O<A, B, T> = (a: A, b?: B) => T; | ||
export declare type Implementation2<A, B, T> = (a: A, b: B) => T; | ||
export declare type Implementation2O<A, B, C, T> = (a: A, b: B, c?: C) => T; | ||
export declare type Implementation3<A, B, C, T> = (a: A, b: B, c: C) => T; | ||
export declare type Implementation3O<A, B, C, D, T> = (a: A, b: B, c: C, d?: D) => T; | ||
export declare type Implementation4<A, B, C, D, T> = (a: A, b: B, c: C, d: D) => T; | ||
export declare type Implementation4O<A, B, C, D, E, T> = (a: A, b: B, c: C, d: D, e?: E) => T; | ||
export declare type Implementation5<A, B, C, D, E, T> = (a: A, b: B, c: C, d: D, e: E) => T; | ||
export declare type Implementation5O<A, B, C, D, E, F, T> = (a: A, b: B, c: C, d: D, e: E, f?: F) => T; | ||
export declare type Implementation6<A, B, C, D, E, F, T> = (a: A, b: B, c: C, d: D, e: E, f: F) => T; | ||
export declare 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 declare type Implementation7<A, B, C, D, E, F, G, T> = (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => T; | ||
export declare 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 declare type Implementation8<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 declare 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> { | ||
@@ -48,2 +64,13 @@ /** | ||
/** | ||
* 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 | ||
@@ -81,16 +108,32 @@ * delegate to `parent`'s implementation. I.e. in terms of dispatch | ||
} | ||
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 declare type AncestorDefs = IObjectOf<Iterable<PropertyKey>>; | ||
@@ -119,8 +162,16 @@ /** | ||
export declare function defmulti<A, B, T>(f: DispatchFn2<A, B>, rels?: AncestorDefs): MultiFn2<A, B, T>; | ||
export declare function defmulti<A, B, T>(f: DispatchFn1O<A, B>, rels?: AncestorDefs): MultiFn1O<A, B, T>; | ||
export declare function defmulti<A, B, C, T>(f: DispatchFn3<A, B, C>, rels?: AncestorDefs): MultiFn3<A, B, C, T>; | ||
export declare function defmulti<A, B, C, T>(f: DispatchFn2O<A, B, C>, rels?: AncestorDefs): MultiFn2O<A, B, C, T>; | ||
export declare function defmulti<A, B, C, D, T>(f: DispatchFn4<A, B, C, D>, rels?: AncestorDefs): MultiFn4<A, B, C, D, T>; | ||
export declare function defmulti<A, B, C, D, T>(f: DispatchFn3O<A, B, C, D>, rels?: AncestorDefs): MultiFn3O<A, B, C, D, T>; | ||
export declare function defmulti<A, B, C, D, E, T>(f: DispatchFn5<A, B, C, D, E>, rels?: AncestorDefs): MultiFn5<A, B, C, D, E, T>; | ||
export declare function defmulti<A, B, C, D, E, T>(f: DispatchFn4O<A, B, C, D, E>, rels?: AncestorDefs): MultiFn4O<A, B, C, D, E, T>; | ||
export declare function defmulti<A, B, C, D, E, F, T>(f: DispatchFn6<A, B, C, D, E, F>, rels?: AncestorDefs): MultiFn6<A, B, C, D, E, F, T>; | ||
export declare function defmulti<A, B, C, D, E, F, T>(f: DispatchFn5O<A, B, C, D, E, F>, rels?: AncestorDefs): MultiFn5O<A, B, C, D, E, F, T>; | ||
export declare function defmulti<A, B, C, D, E, F, G, T>(f: DispatchFn7<A, B, C, D, E, F, G>, rels?: AncestorDefs): MultiFn7<A, B, C, D, E, F, G, T>; | ||
export declare function defmulti<A, B, C, D, E, F, G, T>(f: DispatchFn6O<A, B, C, D, E, F, G>, rels?: AncestorDefs): MultiFn6O<A, B, C, D, E, F, G, T>; | ||
export declare function defmulti<A, B, C, D, E, F, G, H, T>(f: DispatchFn8<A, B, C, D, E, F, G, H>, rels?: AncestorDefs): MultiFn8<A, B, C, D, E, F, G, H, T>; | ||
export declare function defmulti<A, B, C, D, E, F, G, H, T>(f: DispatchFn7O<A, B, C, D, E, F, G, H>, rels?: AncestorDefs): MultiFn7O<A, B, C, D, E, F, G, H, T>; | ||
export declare function defmulti<A, B, C, D, E, F, G, H, I, T>(f: DispatchFn8O<A, B, C, D, E, F, G, H, I>, rels?: AncestorDefs): MultiFn8O<A, B, C, D, E, F, G, H, I, T>; | ||
/** | ||
@@ -162,4 +213,59 @@ * Returns a multi-dispatch function which delegates to one of the | ||
*/ | ||
export declare function defmultiN<T>(impls: { | ||
export declare const defmultiN: <T>(impls: { | ||
[id: number]: Implementation<T>; | ||
}, fallback?: Implementation<T>): MultiFn<T>; | ||
}, fallback?: Implementation<T>) => MultiFn<T>; | ||
/** | ||
* Syntax-sugar intended for sets of multi-methods sharing same dispatch | ||
* values / logic. Takes a dispatch value, an object of "is-a" | ||
* relationships and a number of multi-methods, each with an | ||
* implementation for the given dispatch value. | ||
* | ||
* The relations object has dispatch values (parents) as keys and arrays | ||
* of multi-methods as their values. For each multi-method associates | ||
* the given `type` with the related parent dispatch value to delegate | ||
* to its implementation. | ||
* | ||
* The remaining implementations are associated with their related | ||
* multi-method and the given `type` dispatch value. | ||
* | ||
* ``` | ||
* foo = defmulti((x) => x.id); | ||
* bar = defmulti((x) => x.id); | ||
* bax = defmulti((x) => x.id); | ||
* baz = defmulti((x) => x.id); | ||
* | ||
* // define impls for dispatch value `a` | ||
* implementations( | ||
* "a", | ||
* | ||
* // delegate bax & baz impls to dispatch val `b` | ||
* { | ||
* b: [bax, baz] | ||
* }, | ||
* | ||
* // concrete multi-fn impls | ||
* foo, | ||
* (x) => `foo: ${x.val}`, | ||
* | ||
* bar, | ||
* (x) => `bar: ${x.val.toUpperCase()}` | ||
* ); | ||
* | ||
* // add parent impls | ||
* bax.add("b", (x) => `bax: ${x.id}`); | ||
* baz.add("c", (x) => `baz: ${x.id}`); | ||
* // use "c" impl for "b" | ||
* baz.isa("b", "c"); | ||
* | ||
* foo({ id: "a", val: "alice" }); // "foo: alice" | ||
* bar({ id: "a", val: "alice" }); // "bar: ALICE" | ||
* bax({ id: "a", val: "alice" }); // "bax: a" | ||
* baz({ id: "a", val: "alice" }); // "baz: a" | ||
* | ||
* baz.impls(); // Set { "c", "a", "b" } | ||
* ``` | ||
* | ||
* @param type | ||
* @param impls | ||
*/ | ||
export declare const implementations: (type: string | number | symbol, rels: IObjectOf<MultiFn<any>[]>, ...impls: (MultiFn<any> | Implementation<any>)[]) => void; |
100
index.js
@@ -1,7 +0,4 @@ | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const unsupported_1 = require("@thi.ng/errors/unsupported"); | ||
const illegal_arity_1 = require("@thi.ng/errors/illegal-arity"); | ||
exports.DEFAULT = Symbol(); | ||
function defmulti(f, ancestors) { | ||
import { illegalArgs, unsupported, illegalArity } from "@thi.ng/errors"; | ||
export const DEFAULT = Symbol(); | ||
export function defmulti(f, ancestors) { | ||
const impls = {}; | ||
@@ -11,4 +8,4 @@ const rels = ancestors ? makeRels(ancestors) : {}; | ||
const id = f(...args); | ||
const g = impls[id] || findImpl(impls, rels, id) || impls[exports.DEFAULT]; | ||
return g ? g(...args) : unsupported_1.unsupported(`missing implementation for: "${id.toString()}"`); | ||
const g = impls[id] || findImpl(impls, rels, id) || impls[DEFAULT]; | ||
return g ? g(...args) : unsupported(`missing implementation for: "${id.toString()}"`); | ||
}; | ||
@@ -34,2 +31,6 @@ fn.add = (id, g) => { | ||
}; | ||
fn.callable = (...args) => { | ||
const id = f(...args); | ||
return !!(impls[id] || findImpl(impls, rels, id) || impls[DEFAULT]); | ||
}; | ||
fn.isa = (id, parent) => { | ||
@@ -40,2 +41,10 @@ let val = rels[id]; | ||
}; | ||
fn.impls = () => { | ||
const res = new Set(Object.keys(impls)); | ||
for (let id in rels) { | ||
findImpl(impls, rels, id) && res.add(id); | ||
} | ||
impls[DEFAULT] && res.add(DEFAULT); | ||
return res; | ||
}; | ||
fn.rels = () => rels; | ||
@@ -46,3 +55,2 @@ fn.parents = (id) => rels[id]; | ||
} | ||
exports.defmulti = defmulti; | ||
; | ||
@@ -113,5 +121,5 @@ const findImpl = (impls, rels, id) => { | ||
*/ | ||
function defmultiN(impls, fallback) { | ||
export const defmultiN = (impls, fallback) => { | ||
const fn = defmulti((...args) => args.length); | ||
fn.add(exports.DEFAULT, fallback || ((...args) => illegal_arity_1.illegalArity(args.length))); | ||
fn.add(DEFAULT, fallback || ((...args) => illegalArity(args.length))); | ||
for (let id in impls) { | ||
@@ -121,3 +129,69 @@ fn.add(id, impls[id]); | ||
return fn; | ||
} | ||
exports.defmultiN = defmultiN; | ||
}; | ||
/** | ||
* Syntax-sugar intended for sets of multi-methods sharing same dispatch | ||
* values / logic. Takes a dispatch value, an object of "is-a" | ||
* relationships and a number of multi-methods, each with an | ||
* implementation for the given dispatch value. | ||
* | ||
* The relations object has dispatch values (parents) as keys and arrays | ||
* of multi-methods as their values. For each multi-method associates | ||
* the given `type` with the related parent dispatch value to delegate | ||
* to its implementation. | ||
* | ||
* The remaining implementations are associated with their related | ||
* multi-method and the given `type` dispatch value. | ||
* | ||
* ``` | ||
* foo = defmulti((x) => x.id); | ||
* bar = defmulti((x) => x.id); | ||
* bax = defmulti((x) => x.id); | ||
* baz = defmulti((x) => x.id); | ||
* | ||
* // define impls for dispatch value `a` | ||
* implementations( | ||
* "a", | ||
* | ||
* // delegate bax & baz impls to dispatch val `b` | ||
* { | ||
* b: [bax, baz] | ||
* }, | ||
* | ||
* // concrete multi-fn impls | ||
* foo, | ||
* (x) => `foo: ${x.val}`, | ||
* | ||
* bar, | ||
* (x) => `bar: ${x.val.toUpperCase()}` | ||
* ); | ||
* | ||
* // add parent impls | ||
* bax.add("b", (x) => `bax: ${x.id}`); | ||
* baz.add("c", (x) => `baz: ${x.id}`); | ||
* // use "c" impl for "b" | ||
* baz.isa("b", "c"); | ||
* | ||
* foo({ id: "a", val: "alice" }); // "foo: alice" | ||
* bar({ id: "a", val: "alice" }); // "bar: ALICE" | ||
* bax({ id: "a", val: "alice" }); // "bax: a" | ||
* baz({ id: "a", val: "alice" }); // "baz: a" | ||
* | ||
* baz.impls(); // Set { "c", "a", "b" } | ||
* ``` | ||
* | ||
* @param type | ||
* @param impls | ||
*/ | ||
export const implementations = (type, rels, ...impls) => { | ||
(impls.length & 1) && illegalArgs("expected an even number of implementation items"); | ||
if (rels) { | ||
for (let parent in rels) { | ||
for (let fn of rels[parent]) { | ||
fn.isa(type, parent); | ||
} | ||
} | ||
} | ||
for (let i = 0; i < impls.length; i += 2) { | ||
impls[i].add(type, impls[i + 1]); | ||
} | ||
}; |
{ | ||
"name": "@thi.ng/defmulti", | ||
"version": "0.7.0", | ||
"version": "1.0.0", | ||
"description": "Dynamically extensible multiple dispatch via user supplied dispatch function.", | ||
"main": "./index.js", | ||
"module": "./index.js", | ||
"main": "./lib/index.js", | ||
"umd:main": "./lib/index.umd.js", | ||
"typings": "./index.d.ts", | ||
@@ -15,8 +17,10 @@ "repository": { | ||
"scripts": { | ||
"build": "yarn run clean && tsc --declaration", | ||
"clean": "rm -rf *.js *.d.ts .nyc_output build coverage doc", | ||
"build": "yarn clean && yarn build:es6 && yarn build:bundle", | ||
"build:es6": "tsc --declaration", | ||
"build:bundle": "../../scripts/bundle-module defmulti api errors", | ||
"test": "rimraf build && tsc -p test/tsconfig.json && nyc mocha build/test/*.js", | ||
"clean": "rimraf *.js *.d.ts .nyc_output build coverage doc lib", | ||
"cover": "yarn test && nyc report --reporter=lcov", | ||
"doc": "node_modules/.bin/typedoc --mode modules --out doc src", | ||
"pub": "yarn run build && yarn publish --access public", | ||
"test": "rm -rf build && tsc -p test && nyc mocha build/test/*.js" | ||
"pub": "yarn build && yarn publish --access public" | ||
}, | ||
@@ -28,8 +32,8 @@ "devDependencies": { | ||
"nyc": "^13.1.0", | ||
"typedoc": "^0.13.0", | ||
"typedoc": "^0.14.0", | ||
"typescript": "^3.2.2" | ||
}, | ||
"dependencies": { | ||
"@thi.ng/api": "^4.2.4", | ||
"@thi.ng/errors": "^0.1.12" | ||
"@thi.ng/api": "^5.0.0", | ||
"@thi.ng/errors": "^1.0.0" | ||
}, | ||
@@ -43,3 +47,4 @@ "keywords": [ | ||
}, | ||
"gitHead": "26a29cf15b7817101ce53bc1aa903cc2f88f83c8" | ||
"sideEffects": false, | ||
"gitHead": "348e7303b8b4d2749a02dd43e3f78d711242e4fe" | ||
} |
@@ -31,3 +31,3 @@ # @thi.ng/defmulti | ||
### defmulti | ||
### defmulti() | ||
@@ -47,6 +47,16 @@ `defmulti` returns a new multi-dispatch function using the provided | ||
Implementations for different dispatch values can be added and removed | ||
dynamically by calling `.add(id, fn)` or `.remove(id)` on the returned | ||
function. | ||
The function returned by `defmulti` can be called like any other | ||
function, but also exposes the following operations: | ||
- `.add(id, fn)` - adds new implementation for given dispatch value | ||
- `.remove(id)` - removes implementation for dispatch value | ||
- `.callable(...args)` - takes same args as if calling the | ||
multi-function, but only checks if an implementation exists for the | ||
given args. Returns boolean. | ||
- `.isa(child, parent)` - establish dispatch value relationship hierarchy | ||
- `.impls()` - returns set of all dispatch values which have an implementation | ||
- `.rels()` - return all dispatch value relationships | ||
- `.parents(id)` - direct parents of dispatch value `id` | ||
- `.ancestors(id)` - transitive parents of dispatch value `id` | ||
#### Dispatch value hierarchies | ||
@@ -88,5 +98,11 @@ | ||
// dispatch values w/ implementations | ||
foo.impls(); | ||
// Set { "odd", "even", "number", "23", "42" } | ||
foo(23); // "23 is odd" | ||
foo(42); // "42 is a number" | ||
foo(1); // error (missing impl & no default) | ||
foo.callable(1) // false | ||
``` | ||
@@ -111,4 +127,60 @@ | ||
### defmultiN | ||
### implementations() | ||
Syntax-sugar intended for sets of multi-methods sharing same dispatch | ||
values / logic. Takes a dispatch value, an object of "is-a" | ||
relationships and a number of multi-methods, each with an implementation | ||
for the given dispatch value. | ||
The relations object has dispatch values (parents) as keys and arrays of | ||
multi-methods as their values. For each multi-method associates the | ||
given `type` with the related parent dispatch value to delegate to its | ||
implementation (see `.isa()` above). | ||
The remaining implementations are associated with their related | ||
multi-method and the given `type` dispatch value. | ||
```ts | ||
foo = defmulti((x) => x.id); | ||
bar = defmulti((x) => x.id); | ||
bax = defmulti((x) => x.id); | ||
baz = defmulti((x) => x.id); | ||
// define impls for dispatch value `a` | ||
implementations( | ||
"a", | ||
// delegate bax & baz impls to dispatch val `b` | ||
{ | ||
b: [bax, baz] | ||
}, | ||
// concrete multi-fn impls | ||
foo, | ||
(x) => `foo: ${x.val}`, | ||
bar, | ||
(x) => `bar: ${x.val.toUpperCase()}` | ||
); | ||
// some parent impls for bax & baz | ||
bax.add("b", (x) => `bax: ${x.id}`); | ||
baz.add("c", (x) => `baz: ${x.id}`); | ||
// delegate to use "c" impl for "b" | ||
baz.isa("b", "c"); | ||
foo({ id: "a", val: "alice" }); // "foo: alice" | ||
bar({ id: "a", val: "alice" }); // "bar: ALICE" | ||
bax({ id: "a", val: "alice" }); // "bax: a" | ||
baz({ id: "a", val: "alice" }); // "baz: a" | ||
baz.impls(); // Set { "c", "a", "b" } | ||
``` | ||
Also see the WIP package | ||
[@thi.ng/geom](https://github.com/thi-ng/umbrella/tree/master/packages/geom) | ||
for a concreate realworld usage example. | ||
### defmultiN() | ||
Returns a multi-dispatch function which delegates to one of the provided | ||
@@ -115,0 +187,0 @@ implementations, based on the arity (number of args) when the function |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
61788
10
674
0
290
1
+ Added@thi.ng/api@5.1.0(transitive)
+ Added@thi.ng/errors@1.3.4(transitive)
- Removed@thi.ng/api@4.2.4(transitive)
- Removed@thi.ng/errors@0.1.12(transitive)
Updated@thi.ng/api@^5.0.0
Updated@thi.ng/errors@^1.0.0