yarn add @ephetic/functional
Patterns are checked in order, stopping with the first match. If no patterns match, the generated function will return undefined
.
The pattern wildcard is the function itself (and can be aliased to any symbol you prefer).
import { matcher as m } from 'functional'
const isHi = m(['hi', true])
console.log(isHi('hi')) // true
console.log(isHi('hello')) // undefined
const fact = m(
[1, 1],
[m, n => n * fact(n-1)]
)
const fibo = m(
[n => n <= 2, 1],
[m, n => fibo(n-1) fibo(n-2)]
)
const t = (types, fn) =>
process.env.NODE_ENV == 'production'
? fn
: m([types, fn],
[m, (...args) => {throw `Type Check error: [${args}] doesn't match [${types}].`}])
const Integer = n => n === (n|0)
const addi = t([Integer, Integer], (a,b) => a b)
const NonnegativeInteger = n => Integer(n) && n >= 0
const powish = t([Number, NonnegativeInteger], (b, e) => e > 0 ? b * pow(b, e - 1) : 1)
console.log(powish(2.2,3)) // works
console.log(powish(2,-3)) // throws
const isLikeHi = m([/.*hi.*/, s => `${s} is close enough`])
const secondIsNumber = m(
[ [m, Number], (a,b) => console.log(`${b} is a Number`)],
[ m, (a,b) => console.log(`${b} is not a Number`)]
)
secondIsNumber('asdf', 2) // 2 is a Number
secondIsNumber(2, 'asdf') // asdf is not a Number
Note:
Number
here is the Number constructor which returns falsyNaN
for anything that doesn't parse as a number. Contructor type-checking does not currently work (it can cause false positives when called internally as a predicate).- To test a single array, wrap them in an array to indicate an argument or use an object literal with index keys; e.g.
[[m, m]]
or{0: m, 1: m, length: 2}
(includelength
for exact match).
const isDuckman = m([{name: 'Duckman', age:40}, () => console.log('Duuuuckmaaaaan!')])
isDuckman({name: 'Duckman', age:40}) // Duuuuckmaaaaan!
isDuckman({name: 'Duckman'}) // undefined
const isDuckPerson = m([{name: m, age: m}, () => console.log('wubba lubba dub dub')])
isDuckPerson({name: 'Rick', age: 55}) // wubba lubba dub dub
Uses itself as wildcard to leave arbitrary parameters unbound.
import { partial as p } from 'functional'
const add = (a,b) => a b
const div = (a,b) => a / b
const add1 = p(add, 1)
const halve = p(div, p, 2)