feat: Allow self-reference in implementations #4
@ -5,6 +5,7 @@ export default class PocomathInstance {
|
||||
constructor(name) {
|
||||
this.name = name
|
||||
this._imps = {}
|
||||
this._affects = {}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -46,6 +47,14 @@ export default class PocomathInstance {
|
||||
`Conflicting definitions of ${signature} for ${name}`)
|
||||
} else {
|
||||
opImps[signature] = implementations[signature]
|
||||
for (const dep of implementations[signature][0]) {
|
||||
const depname = dep.split('(', 1)[0]
|
||||
if (depname === 'self') continue
|
||||
if (!(depname in this._affects)) {
|
||||
this._affects[depname] = new Set()
|
||||
}
|
||||
this._affects[depname].add(name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,6 +71,11 @@ export default class PocomathInstance {
|
||||
if (!(name in this._imps)) {
|
||||
this._imps[name] = {}
|
||||
}
|
||||
if (name in this._affects) {
|
||||
for (const ancestor of this._affects[name]) {
|
||||
this._invalidate(ancestor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,4 +1,8 @@
|
||||
import './Complex.mjs'
|
||||
import {numComplex} from './Complex.mjs'
|
||||
export const negate = {
|
||||
Complex: [['self'], ref => z => ({re: ref.self(z.re), im: ref.self(z.im)})]
|
||||
/* need a "base case" to avoid infinite self-reference */
|
||||
Complex: [['self'], ref => z => {
|
||||
if (numComplex(z)) return {re: -z.re, im: -z.im}
|
||||
return {re: ref.self(z.re), im: ref.self(z.im)}
|
||||
}]
|
||||
}
|
||||
|
@ -4,12 +4,16 @@ import typed from 'typed-function'
|
||||
import PocomathInstance from '../PocomathInstance.mjs'
|
||||
import * as numbers from '../number/all.mjs'
|
||||
import * as complex from '../complex/all.mjs'
|
||||
import * as complexAdd from '../complex/add.mjs'
|
||||
import * as complexNegate from '../complex/negate.mjs'
|
||||
|
||||
const bw = new PocomathInstance('backwards')
|
||||
describe('A custom instance', () => {
|
||||
it("works when partially assembled", () => {
|
||||
bw.install(complex)
|
||||
assert.deepStrictEqual(bw.add(2, bw.complex(0, 3)), {re: 2, im: 3})
|
||||
assert.deepStrictEqual(bw.negate(2), bw.complex(-2,-0))
|
||||
assert.deepStrictEqual(bw.subtract(2, bw.complex(0, 3)), {re: 2, im: -3})
|
||||
})
|
||||
|
||||
it("can be assembled in any order", () => {
|
||||
@ -23,4 +27,15 @@ describe('A custom instance', () => {
|
||||
math.complex(11, -4)) // note both instances coexist
|
||||
assert.deepStrictEqual(bw.negate(math.complex(3, '8')).im, -8)
|
||||
})
|
||||
|
||||
it("can be assembled piecemeal", () => {
|
||||
const pm = new PocomathInstance('piecemeal')
|
||||
pm.install(numbers)
|
||||
assert.strictEqual(pm.subtract(5, 10), -5)
|
||||
pm.install(complexAdd)
|
||||
pm.install(complexNegate)
|
||||
// Should be enough to allow complex subtraction, as subtract is generic
|
||||
assert.deepStrictEqual(
|
||||
pm.subtract({re:5, im:0}, {re:10, im:1}), {re:-5, im: -1})
|
||||
})
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user