Creates a group of related functions from a naming function, a value deriver function, and an array of primitive values.
yarn add cliquer
# or
npm i cliquer
clique :: (a -> String) -> (a -> Any) -> Array a -> Object
Takes a namer function, a function to derive a value, and an array of strings that becomes input for both functions, returns an object where each key value pair is generated by [namer, valueDeriver] respectively.
import { clique } from 'cliquer';
const concat = x => y => y.concat(x)
const always = x => () => x
const consts = clique(concat('Bar'), always)
const C = consts(['a', 'b'])
C.bBar() //=> 'b'
simpleClique :: (a -> Any) -> Array a -> Object
This is simply clique partially applied with an identity function, so that each key is either a literal or toString
representation of the input value.
import { simpleClique } from 'cliquer';
const always = x => () => x
const consts = simpleClique(always)
const C = consts(['a', 'b'])
C.b() //=> 'b'
Cliquer was originally inspired by a utility in drboolean's lenses library called makeLenses
which takes an array of strings and returns an object of named lenses:
import { lensProp } from 'ramda'
import { makeLenses, view } from 'lenses'
const obj = {
foe: { name: 'marley' },
friend: { name: 'me' },
}
// makeLenses allows a DRY-er approach like
const L = makeLenses(['friend', 'name'])
// instead of
const friend = lensProp('friend')
const name = lensProp('name')
const friendName = compose(L.friend, L.name)
view(friendName, obj) // => 'me'
This got me thinking, how many things in javascript would benefit from a similar shortcut? So a simple curried factory function was born that took two functions, one to generate the key name, and one to define the function. Turns out this is a super useful pattern for creating utility groups.
import R from 'ramda'
const keys = ['beer', 'me']
// Pass an identity function so each key is named literally
const simpleClique = clique(x => x)
// Simple equality checks
const eqs = simpleClique(R.equals)
const E = eqs(keys)
E.beer('beer') //=> true
E.me('beer') //=> false
// Constant generators
const consts = simpleClique(R.always)
const C = consts(keys)
C.beer() //=> 'beer'
// Regex group
const firstChars = simpleClique(x => new RegExp(`^${x}`))
const F = firstChars(['a', 'b'])
R.test(F.a, 'abc') //=> true
R.test(F.b, 'abc') //=> false
/* Even more complex things! */
// Pass a function that names each key by appending `bird`
const birdClique =
clique(x => x.concat('bird'))
const url =
'https://isthisbirdathing.com/api/birds'
const birdFetchers =
birdClique(x => fetch(`${url}/${x}bird`).then(x => x.json()) )
const B =
birdFetchers(['blue', 'shoe', 'fackle'])
B.facklebird()
.then(console.log) //=> { isAThing: 'um.. no' }
B.bluebird()
.then(console.log) //=> { isAThing: 'yep 🐦' }
Get the picture? If not submit a PR to help me explain this better or to add more imaginative/hilarious examples 💖