Last active
January 1, 2018 06:21
-
-
Save wl00887404/701d2e674babade309dc9d3259ad10b1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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