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:
Numberhere is the Number constructor which returns falsyNaNfor 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}(includelengthfor 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)