diff --git a/src/core/TypeDispatcher.js b/src/core/TypeDispatcher.js index b763fde..23e1d54 100644 --- a/src/core/TypeDispatcher.js +++ b/src/core/TypeDispatcher.js @@ -151,7 +151,7 @@ export class TypeDispatcher { throw new ReferenceError(`no method or value for key '${key}'`) } - if (this.resolve._genDepsOf?.length) _addToDeps(key, types) + if (this.resolve._genDepsOf?.length) this._addToDeps(key, types) const behave = this._behaviors[key] if (behave.has(types)) return behave.get(types) @@ -192,8 +192,6 @@ export class TypeDispatcher { try { theBehavior = item(DependencyRecorder(this, [], this), template) } catch { - // Didn't work as a factory, so guess we were wrong; just - // make this entity the behavior: behave.set(types, item) return item } finally { @@ -201,6 +199,7 @@ export class TypeDispatcher { } if (typeof theBehavior === 'function' && theBehavior.length + && Array.isArray(template) && template.some(elt => Array.isArray(elt)) ) { // have to wrap the behavior to collect the actual arguments diff --git a/src/core/__test__/TypeDispatcher.spec.js b/src/core/__test__/TypeDispatcher.spec.js index 2a61b17..009b8ef 100644 --- a/src/core/__test__/TypeDispatcher.spec.js +++ b/src/core/__test__/TypeDispatcher.spec.js @@ -1,9 +1,11 @@ import assert from 'assert' import {TypeDispatcher} from '../TypeDispatcher.js' import {numbers} from '../../numbers.js' +import {generics} from '../../generics.js' import {onType} from "#core/helpers.js" import {Any} from "#core/TypePatterns.js" import {Returns} from "#core/Type.js" +import {plain} from "#number/helpers.js" describe('TypeDispatcher', () => { it('can build in stages', () => { @@ -38,4 +40,11 @@ describe('TypeDispatcher', () => { incremental.add.resolve([Undefined, Number]).returns, Number) }) + it('changes methods when their dependencies change', () => { + const gnmath = new TypeDispatcher(generics, numbers) + assert.strictEqual(gnmath.square(-2.5), 6.25) + // change multiplication of number to floor its first argument (?!) + gnmath.merge({multiply: plain((a,b) => Math.floor(a) * b)}) + assert.strictEqual(gnmath.square(-2.5), 7.5) + }) }) diff --git a/src/generic/__test__/arithmetic.spec.js b/src/generic/__test__/arithmetic.spec.js new file mode 100644 index 0000000..f1d6043 --- /dev/null +++ b/src/generic/__test__/arithmetic.spec.js @@ -0,0 +1,11 @@ +import assert from 'assert' +import math from '#nanomath' + +describe('generic arithmetic', () => { + it('squares anything', () => { + assert.strictEqual(math.square(7), 49) + assert.strictEqual( + math.square.resolve([math.types.Number]).returns, + math.types.Number) + }) +}) diff --git a/src/generic/all.js b/src/generic/all.js new file mode 100644 index 0000000..0d39ba5 --- /dev/null +++ b/src/generic/all.js @@ -0,0 +1 @@ +export * as arithmetic from './arithmetic.js' diff --git a/src/generic/arithmetic.js b/src/generic/arithmetic.js new file mode 100644 index 0000000..433f373 --- /dev/null +++ b/src/generic/arithmetic.js @@ -0,0 +1,8 @@ +import {onType} from '#core/helpers.js' +import {Returns} from '#core/Type.js' +import {Any} from '#core/TypePatterns.js' + +export const square = onType(Any, (math, T) => { + const mult = math.multiply.resolve([T, T]) + return Returns(mult.returns, a => mult(a, a)) +}) diff --git a/src/generics.js b/src/generics.js new file mode 100644 index 0000000..0ce5d7b --- /dev/null +++ b/src/generics.js @@ -0,0 +1 @@ +export * as generics from './generic/all.js' diff --git a/src/nanomath.js b/src/nanomath.js index ebb055e..c32247d 100644 --- a/src/nanomath.js +++ b/src/nanomath.js @@ -1,6 +1,7 @@ +import {generics} from './generics.js' import {numbers} from './numbers.js' import {TypeDispatcher} from '#core/TypeDispatcher.js' -const math = new TypeDispatcher(numbers) +const math = new TypeDispatcher(generics, numbers) export default math