Implements a totally simplistic "poortf" mutable typed function and a picomath instance generator, as well as the very beginnings of a number type and one generic function and a default full picomath instance. Also provides some tests which serve as usage examples.main
parent
36cc91ca95
commit
536656bfe8
@ -0,0 +1,9 @@ |
||||
export default function create(pmath) { |
||||
const add = pmath('add') |
||||
const negate = pmath('negate') |
||||
if (!pmath.subtract) { // avoid double definition at cost of extensibility
|
||||
pmath('subtract', [args => args.length === 2, |
||||
(x, y) => add(x, negate(y))]) |
||||
} |
||||
return pmath.subtract |
||||
} |
@ -0,0 +1,6 @@ |
||||
import { allNumbers } from './number.js' |
||||
|
||||
export default function create(pmath) { |
||||
return pmath('add', [allNumbers, |
||||
(...addends) => addends.reduce((x,y) => x+y, 0)]) |
||||
} |
@ -0,0 +1,12 @@ |
||||
import createNumber from './number.js' |
||||
import createAdd from './add.js' |
||||
import createNegate from './negate.js' |
||||
import createSubtract from '../generic/subtract.js' |
||||
|
||||
export default function create(pmath) { |
||||
createNumber(pmath) |
||||
createAdd(pmath) |
||||
createNegate(pmath) |
||||
createSubtract(pmath) |
||||
// not sure if there's anything reasonable to return here
|
||||
} |
@ -0,0 +1,7 @@ |
||||
import { oneNumber } from './number.js' |
||||
|
||||
export default function create(pmath) { |
||||
return pmath('negate', [oneNumber, n => -n]) |
||||
} |
||||
|
||||
|
@ -0,0 +1,14 @@ |
||||
export function allNumbers(args) { |
||||
for (let i = 0; i < args.length; ++i) { |
||||
if (typeof args[i] !== 'number') return false |
||||
} |
||||
return true |
||||
} |
||||
|
||||
export function oneNumber(args) { |
||||
return args.length === 1 && typeof args[0] === 'number' |
||||
} |
||||
|
||||
export default function create(pmath) { |
||||
return pmath('number', [() => true, x => Number(x)]) |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,8 @@ |
||||
/* Core of picomath: generates an instance */ |
||||
import picomathInstance from './picomathInstance.js' |
||||
import createNumbers from './number/all.js' |
||||
|
||||
const math = picomathInstance('math') |
||||
createNumbers(math) |
||||
|
||||
export default math |
@ -0,0 +1,20 @@ |
||||
/* Core of picomath: generates an instance */ |
||||
import poortf from './poortf.js' |
||||
|
||||
export default function picomathInstance (instName) { |
||||
function fn (name, imps) { |
||||
if (name in fn) { |
||||
fn[name].addImps(imps) |
||||
} else { |
||||
fn[name] = poortf(name, imps) |
||||
} |
||||
return fn[name] |
||||
} |
||||
|
||||
Object.defineProperty(fn, 'name', {value: instName}) |
||||
|
||||
return fn |
||||
} |
||||
|
||||
|
||||
|
@ -0,0 +1,27 @@ |
||||
/* Totally minimal "typed functions" */ |
||||
|
||||
const addImps = (dest, imps) => { |
||||
if (imps) { |
||||
if (!Array.isArray(imps[0])) imps = [imps] |
||||
for (const imp of imps) dest.push(imp) |
||||
} |
||||
} |
||||
|
||||
export default function poortf (name, imps) { |
||||
/* This is the (function) object we will return */ |
||||
function fn () { |
||||
for (const imp of fn.imps) { |
||||
if (imp[0](arguments)) return imp[1].apply(null, arguments) |
||||
} |
||||
throw new TypeError( |
||||
`TF ${fn.name}: No match for ${arguments[0]}, ${arguments[1]}, ...`) |
||||
} |
||||
|
||||
/* Now dress it up for use */ |
||||
Object.defineProperty(fn, 'name', {value: name}) |
||||
fn.imps = [] |
||||
addImps(fn.imps, imps) |
||||
fn.addImps = newI => addImps(fn.imps, newI) |
||||
|
||||
return fn |
||||
} |
@ -0,0 +1,15 @@ |
||||
import assert from 'assert' |
||||
import math from '../picomath.js' |
||||
|
||||
describe('The default full picomath instance "math"', () => { |
||||
it('performs basic arithmetic operations', () => { |
||||
assert.strictEqual(math.subtract(16, math.add(3,4,2)), 7) |
||||
assert.strictEqual(math.negate(math.number('8')), -8) |
||||
}) |
||||
|
||||
it('can be extended', () => { |
||||
math('add', [args => typeof args[0] === 'string', |
||||
(...addends) => addends.reduce((x,y) => x+y, '')]) |
||||
assert.strictEqual(math.add('Kilroy',' is here'), 'Kilroy is here') |
||||
}) |
||||
}) |
@ -0,0 +1,13 @@ |
||||
import assert from 'assert' |
||||
import picomathInstance from '../picomathInstance.js' |
||||
|
||||
describe('picomath core', () => { |
||||
it('creates an instance that can define TFs', () => { |
||||
const pmath = picomathInstance('pmath') |
||||
pmath('add', [() => true, (a,b) => a+b]) |
||||
assert.strictEqual(pmath.add(2,2), 4) |
||||
assert.strictEqual(pmath.add('Kilroy', 17), 'Kilroy17') |
||||
assert.strictEqual(pmath.add(1), NaN) |
||||
// I guess + never throws!
|
||||
}) |
||||
}) |
@ -0,0 +1,41 @@ |
||||
import assert from 'assert' |
||||
import poortf from '../poortf.js' |
||||
|
||||
describe('poortf', () => { |
||||
const slate = poortf('slate') |
||||
it('creates an empty tf', () => { |
||||
assert.throws(() => slate('empty'), TypeError) |
||||
assert.throws(() => slate('empty'), /slate.*empty/) |
||||
}) |
||||
|
||||
const add = poortf('add', [ |
||||
[args => Array.from(args).every(a => typeof a === 'number'), |
||||
(a, b) => a+b], |
||||
[args => Array.from(args).every(a => typeof a === 'boolean'), |
||||
(p, q) => p || q] |
||||
]) |
||||
|
||||
it('creates a tf with initial behaviors', () => { |
||||
assert.strictEqual(add(2,2), 4) |
||||
assert.strictEqual(add(true, false), true) |
||||
assert.throws(() => add('kilroy'), TypeError) |
||||
}) |
||||
|
||||
it('extends an empty tf', () => { |
||||
slate.addImps([ |
||||
[args => typeof args[0] === 'string', s => s + ' wuz here'], |
||||
[args => typeof args[0] === 'number', () => 'I am not a number'] |
||||
]) |
||||
assert.strictEqual(slate('Kilroy', 'was here'), 'Kilroy wuz here') |
||||
assert.strictEqual(slate(2, 'was here'), 'I am not a number') |
||||
assert.throws(() => slate(['Ha!']), TypeError) |
||||
}) |
||||
|
||||
it('extends a tf with other behaviors', () => { |
||||
add.addImps([args => typeof args[0] === 'string', (s,x) => s + x]), |
||||
assert.strictEqual(add('Kilroy', 23), 'Kilroy23') |
||||
assert.throws(() => add(['Ha!'], 'gotcha'), TypeError) |
||||
}) |
||||
}) |
||||
|
||||
|
Loading…
Reference in new issue