unfold
js
const unfold = (iteratorFn, seedValue, list = []) => {
const either = iteratorFn(seedValue);
if (either) {
const [result, nextSeedValue] = either;
return unfold(iteratorFn, nextSeedValue, [...list, result])
} else {
return list;
}
};
const fn = n => {
return n > 50
? false
: [-n, n + 10]
};
console.log(unfold(fn, 10));
//=> [-10, -20, -30, -40, -50]
console.log(unfold(fn, 60));
//=> []
always
js
const always = v => _ => v
const five = always(5)
console.log(five()) // 5
boolean
ts
export const toBool = function(value: any): boolean {
return Boolean(value)
}
export const not = function(value: any): boolean {
return !toBool(value)
}
curry
js
const curry1 = fn => arg => fn(arg)
parseInt('11') // => 11
parseInt('11', 2) // => 3
['11', '11', '11'].map(parseInt)
// => [11, NaN, 3]
['11', '11', '11'].map(curry1(parseInt))
// => [11, 11, 11]
const curry2 = fn => arg1 => arg2 => fn(arg1, arg2)
const map = curry2((fn, arr) => arr.map(fn))
map(v => v * 10)([1, 2, 3])
// [10, 20, 30]
is-same
ts
export const isSame = function<T>(src: T) {
return (target: T): boolean => Object.is(src, target)
}
console.log(isSame('foo')('foo') ===true)
console.log(isSame(window)(window) ===true)
console.log(isSame('foo')('bar') ===false)
console.log(isSame([])([]) ===false)
var test = { a: 1 }
console.log(isSame(test)(test) ===true)
console.log(isSame(null)(null) ===true)
console.log(isSame(0)(-0) === false)
console.log(isSame(-0)(-0) === true)
console.log(isSame(NaN)(0/0) ===true)
memoize
js
const memoize = (fn) => {
const cache = {}
return (n) => {
if (!cache[n]) {
cache[n] = fn(n)
}
return cache[n]
}
}
once
ts
type OnceCallback<T> = (value?: T) => void
export const once = function<T>(callback: OnceCallback<T>): OnceCallback<T> {
let isCalled = false
return function(value?: T): void {
if (!isCalled) {
isCalled = true
callback(value)
}
}
}
const onceFn = once(console.log)
onceFn('test')
onceFn('test')
onceFn('test')
onceFn('test')
partial
js
const partial = (fn, ...arg1) => (...arg2) => fn(...arg1, ...arg2)
const add = (a, b) => a + b
const add10 = partial(add, 10)
add10(5) // 15
const addAll = (a, b, c, d) => a + b + c + d
const addTwo = partial(addAll, 10, 10)
addTwo(5, 5) // 30
pipe
js
const pipe = (fn, ...fns) => (...arg) => {
return fns.reduce((acc, fn) => fn(acc), fn(...arg))
}
pipe(
v => v * 10,
v => `${v}%`,
console.log
)(10)
// 100%
plucker
js
const plucker = field => obj => (obj && obj[field])
const best = { title: '인피니티워', author: 'Peter' }
const books = [{title: '스파이더맨'}, {title: '아이언맨'}, {title: '토르'}]
const extractTitle = plucker('title')
const extractThird = plucker(2)
extractTitle(best) // '인피니티워'
extractThird(books) // {title: '토르'}
range
js
const range = length => Array.from({length}, (_, i) => i)
module.exports = range
tab
ts
export const tap = function<T>(callback: (value: T) => void) {
return (value: T): T => {
callback(value)
return value
}
}
fp
js
const range = require('./range')
const chunk = require('./chunk')
const each = iter => (list) => {
for (let i = 0, len = list.length; i < len; i++) {
iter(list[i], i, list, len)
}
return list
}
const loop = iter => len => {
for (let i = 0; i < len; i++) {
iter(i, len)
}
return len
}
const map = iter => list => {
const newList = []
each(item => {
newList.push(iter(item))
})(list)
return newList
}
const filter = iter => list => {
const newList = []
each(item => {
if (iter(item)) {
newList.push(item)
}
})(list)
return newList
}
const find = iter => list => {
for (let i = 0, len = list.length; i < len; i++) {
if (iter(list[i], i, list)) return list[i]
}
return null
}
const findIndex = iter => list => {
for (let i = 0, len = list.length; i < len; i++) {
if (iter(list[i], i, list)) return i
}
return -1
}
const reduce = (init, iter) => list => {
each((item) => {
init = iter(init, item)
})(list)
return init
}
const pipe = (...fns) => res => {
return reduce(res, (res, fn) => fn(res))(fns)
}
const divEq = (...fns) => val => { // Divided Equal
each((fn) => fn(val))(fns)
return val
}
const isUndefined = (obj) => typeof obj === 'undefined'
const negate = v => !v
const clone = (obj) => {
if (typeof (obj) !== 'object') {
return obj
}
var copiedObj = obj.constructor()
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) {
copiedObj[attr] = clone(obj[attr])
}
}
return copiedObj
}
const merge = (defaultOptions, _options) => {
var newOptions = clone(_options)
for (var keyName in defaultOptions) {
if (isUndefined(newOptions[keyName])) {
newOptions[keyName] = defaultOptions[keyName]
}
}
return newOptions
}
module.exports = {
each,
loop,
map,
filter,
find,
findIndex,
reduce,
pipe,
divEq,
isUndefined,
negate,
clone,
merge,
range,
chunk
}
js
const reduce = (arr, iter, def) => arr.reduce(iter, def)
const arr = []
for (let char of '12345') {
arr.push(char)
}
console.log(arr) // => ['1','2','3','4','5']
const arr2 = reduce([...'12345'], (acc, val) => {
acc.push(val)
return acc
}, [])
console.log(arr2)