feat(poortf): add concept of 'author' to an imp of a TF
And make it so that if the same author adds imps again, they replace the previous imps from that author. Use this feature to avoid the explicit check for double-inclusion in subtract, and test it worked.
This commit is contained in:
parent
2c1b6c3364
commit
00a7f79552
@ -1,9 +1,9 @@
|
|||||||
export default function create(pmath) {
|
export default function create(pmath) {
|
||||||
const add = pmath('add')
|
const add = pmath('add')
|
||||||
const negate = pmath('negate')
|
const negate = pmath('negate')
|
||||||
if (!pmath.subtract) { // avoid double definition at cost of extensibility
|
return pmath(
|
||||||
pmath('subtract', [args => args.length === 2,
|
'subtract',
|
||||||
(x, y) => add(x, negate(y))])
|
[args => args.length === 2, (x, y) => add(x, negate(y))],
|
||||||
}
|
create)
|
||||||
return pmath.subtract
|
return pmath.subtract
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,11 @@ export default function picomathInstance (instName) {
|
|||||||
* as a function, it takes a name and 0 or more implementations add adds
|
* as a function, it takes a name and 0 or more implementations add adds
|
||||||
* them to its poortf property named name, returning that property value.
|
* them to its poortf property named name, returning that property value.
|
||||||
*/
|
*/
|
||||||
function fn (name, imps) {
|
function fn (name, imps, author) {
|
||||||
if (name in fn) {
|
if (name in fn) {
|
||||||
fn[name].addImps(imps)
|
fn[name].addImps(imps, author)
|
||||||
} else {
|
} else {
|
||||||
fn[name] = poortf(name, imps)
|
fn[name] = poortf(name, imps, author)
|
||||||
}
|
}
|
||||||
return fn[name]
|
return fn[name]
|
||||||
}
|
}
|
||||||
|
29
poortf.js
29
poortf.js
@ -1,13 +1,29 @@
|
|||||||
/* Totally minimal "typed functions" */
|
/* Totally minimal "typed functions" */
|
||||||
|
|
||||||
const addImps = (dest, imps) => {
|
/* helper: dest is really a TF and imps is either nothing, an imp, or
|
||||||
|
* an array of implementations. author is the entity responsible for these
|
||||||
|
* implementations.
|
||||||
|
*/
|
||||||
|
const addImps = (dest, imps, author) => {
|
||||||
if (imps) {
|
if (imps) {
|
||||||
if (!Array.isArray(imps[0])) imps = [imps]
|
if (!Array.isArray(imps[0])) imps = [imps]
|
||||||
for (const imp of imps) dest.push(imp)
|
if (author) {
|
||||||
|
if (dest.authors.has(author)) {
|
||||||
|
const [count, index] = dest.authors.get(author)
|
||||||
|
if (count) dest.imps.splice(index, count)
|
||||||
|
}
|
||||||
|
dest.authors.set(author, [imps.length, dest.imps.length])
|
||||||
|
}
|
||||||
|
for (const imp of imps) dest.imps.push(imp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Create a TF, optionally adding some initial imps and further optionally
|
||||||
export default function poortf (name, imps) {
|
* registering them to an author. There are two advantages to author
|
||||||
|
* registration: (1) if the same author adds implementations, the prior imps
|
||||||
|
* will be deleted, and (2) the author can be invalidated, and the TF will
|
||||||
|
* lazily call the author back the next time it is called to re-add the imps.
|
||||||
|
*/
|
||||||
|
export default function poortf (name, imps, author) {
|
||||||
/* This is the (function) object we will return */
|
/* This is the (function) object we will return */
|
||||||
function fn () {
|
function fn () {
|
||||||
for (const imp of fn.imps) {
|
for (const imp of fn.imps) {
|
||||||
@ -20,8 +36,9 @@ export default function poortf (name, imps) {
|
|||||||
/* Now dress it up for use */
|
/* Now dress it up for use */
|
||||||
Object.defineProperty(fn, 'name', {value: name})
|
Object.defineProperty(fn, 'name', {value: name})
|
||||||
fn.imps = []
|
fn.imps = []
|
||||||
addImps(fn.imps, imps)
|
fn.authors = new Map() // tracks who made each implementation
|
||||||
fn.addImps = newI => addImps(fn.imps, newI)
|
addImps(fn, imps, author)
|
||||||
|
fn.addImps = (newI, author) => addImps(fn, newI, author)
|
||||||
|
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
@ -20,4 +20,8 @@ describe('The default full picomath instance "math"', () => {
|
|||||||
math.complex(11, -4))
|
math.complex(11, -4))
|
||||||
assert.deepStrictEqual(math.negate(math.complex(3, '8')).im, -8)
|
assert.deepStrictEqual(math.negate(math.complex(3, '8')).im, -8)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not double-define subtract', () => {
|
||||||
|
assert.deepStrictEqual(math.subtract.imps.length, 1)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user