Skip to content

Instantly share code, notes, and snippets.

@wl00887404
Last active January 1, 2018 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wl00887404/701d2e674babade309dc9d3259ad10b1 to your computer and use it in GitHub Desktop.
Save wl00887404/701d2e674babade309dc9d3259ad10b1 to your computer and use it in GitHub Desktop.
const head = ([x, ...xs]) => x
const tail = ([_, ...xs]) => xs
const last = array => head(array.slice(-1))
const init = array => array.slice(0, -1)
const __ = {
toString: _ => 'Curry Placeholder'
}
Object.freeze(__)
const curry = func => {
const replacePlaceholder = (old, args, acc = []) => {
if (old.length == 0) {
return [...acc, ...args]
} else {
const [x, ...xs] = old
if (x === __) {
const [y, ...ys] = args
return replacePlaceholder(xs, ys, [...acc, y])
} else {
return replacePlaceholder(xs, args, [...acc, x])
}
}
}
const continueCurry = (old, ...args) => {
const now = replacePlaceholder(old, args)
const { length } = now.filter(x => x !== __)
if (func.length <= length) {
return func.apply(null, now)
} else {
return continueCurry.bind(null, now)
}
}
return continueCurry.bind(null, [])
}
const zip = curry((array1, array2) => {
if (array1.length == 0 || array2.length == 0) {
return []
} else {
const [x, ...xs] = array1
const [y, ...ys] = array2
return [[x, y], ...zip(xs, ys)]
}
})
const quickSort = array => {
if (array.length < 2) {
return array
} else {
const [x, ...xs] = array
const left = xs.filter(el => el < x)
const right = xs.filter(el => el >= x)
return [...quickSort(left), x, ...quickSort(right)]
}
}
const range = length => Array.from({ length }, (_, i) => i)
const repeat = length => x => Array.from({ length }, _ => x)
const map = curry((func, array) => {
if (array.length == 0) {
return []
} else {
const [x, ...xs] = array
return [func(x), ...map(func, xs)]
}
})
const filter = curry((func, array) => {
if (array.length == 0) {
return []
} else {
const [x, ...xs] = array
const filtered = func(x) ? [x] : []
return [...filtered, ...filter(func, xs)]
}
})
const reduce = curry((func, acc, array) => {
if (array.length == 0) {
return acc
} else {
const [x, ...xs] = array
return reduce(func, func(acc, x), xs)
}
})
const flip = func => curry((y, x, ...args) => func(x, y, ...args))
const max = reduce((acc, el) => (acc > el ? acc : el), -Infinity)
const min = reduce((acc, el) => (acc < el ? acc : el), Infinity)
const reverse = reduce((acc, el) => [el, ...acc], [])
const compose = (...funcs) =>
(...args) => {
// Compose 是從最後往回執行
// 因為第一次可以接受多個參數,所以需要特別處理
const initFuncs = funcs.slice(0, -1) // 除了最後一個 func
const [lastFunc] = funcs.slice(-1) // 最後一個 func
return initFuncs.reduceRight(
(acc, func) => func(acc),
lastFunc.apply(null, args)
)
}
const pipe = (...funcs) =>
(...args) => {
// 相反順序的 Compose
// 因為第一次可以接受多個參數,所以需要特別處理
const [hFunc, ...tFuncs] = funcs
return tFuncs.reduce((
acc, func) => func(acc),
hFunc.apply(null, args)
)
}
const composeP = (...funcs) =>
x =>
funcs.reduceRight(
(acc, func) => acc.then(func),
Promise.resolve(x)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment