updeep-remeda/lib/util/curry.js

127 lines
3.3 KiB
JavaScript
Raw Normal View History

2017-04-19 00:47:53 +00:00
/* eslint no-shadow:0, no-param-reassign:0 prefer-rest-params:0 */
2017-04-19 00:55:46 +00:00
export const _ = '@@updeep/placeholder'
2015-08-12 15:35:10 +00:00
function countArguments(args, max) {
2017-04-19 00:55:46 +00:00
let n = args.length
if (n > max) n = max
2015-08-12 15:35:10 +00:00
while (args[n - 1] === _) {
2017-04-19 00:55:46 +00:00
n -= 1
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
return n
2015-08-12 15:35:10 +00:00
}
2015-08-12 06:41:03 +00:00
export function curry1(fn) {
2016-01-13 15:58:55 +00:00
return function curried(a, ...args) {
2017-04-19 00:55:46 +00:00
const [b, c] = args
const n = countArguments(arguments)
2015-08-12 06:41:03 +00:00
2017-04-19 00:55:46 +00:00
if (n >= 1) return fn(a, b, c)
return curried
}
2015-08-12 06:41:03 +00:00
}
export function curry2(fn) {
2016-01-13 15:58:55 +00:00
return function curried(a, b, ...args) {
2017-04-19 00:55:46 +00:00
const [c, d] = args
const n = countArguments(arguments, 2)
2015-08-12 15:35:10 +00:00
if (b === _ || c === _ || d === _) {
2017-04-19 00:55:46 +00:00
throw new Error(
'Can only use placeholder on first argument of this function.'
)
2015-08-12 15:35:10 +00:00
}
if (n >= 2) {
2017-04-19 00:55:46 +00:00
if (a === _) return curry1((a, c, d) => fn(a, b, c, d))
return fn(a, b, c, d)
2015-08-12 15:35:10 +00:00
}
2015-08-12 06:41:03 +00:00
2017-04-19 00:55:46 +00:00
if (n === 1) return curry1((b, c, d) => fn(a, b, c, d))
return curried
}
2015-08-12 06:41:03 +00:00
}
export function curry3(fn) {
2016-01-13 15:58:55 +00:00
return function curried(a, b, c, ...args) {
2017-04-19 00:55:46 +00:00
const [d, e] = args
const n = countArguments(arguments, 3)
2015-08-12 15:35:10 +00:00
if (c === _ || d === _ || e === _) {
2017-04-19 00:55:46 +00:00
throw new Error(
'Can only use placeholder on first or second argument of this function.'
)
2015-08-12 15:35:10 +00:00
}
if (n >= 3) {
if (a === _) {
2017-04-19 00:55:46 +00:00
if (b === _) return curry2((a, b, d, e) => fn(a, b, c, d, e))
return curry1((a, d, e) => fn(a, b, c, d, e))
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
if (b === _) return curry1((b, d, e) => fn(a, b, c, d, e))
return fn(a, b, c, d, e)
2015-08-12 15:35:10 +00:00
}
if (n === 2) {
2017-04-19 00:55:46 +00:00
if (a === _) return curry2((a, c, d, e) => fn(a, b, c, d, e))
return curry1((c, d, e) => fn(a, b, c, d, e))
2015-08-12 15:35:10 +00:00
}
2015-08-12 06:41:03 +00:00
2017-04-19 00:55:46 +00:00
if (n === 1) return curry2((b, c, d, e) => fn(a, b, c, d, e))
2015-08-12 15:35:10 +00:00
2017-04-19 00:55:46 +00:00
return curried
}
2015-08-12 06:41:03 +00:00
}
export function curry4(fn) {
2016-01-13 15:58:55 +00:00
return function curried(a, b, c, d, ...args) {
2017-04-19 00:55:46 +00:00
const [e, f] = args
const n = countArguments(arguments, 4)
2015-08-12 15:35:10 +00:00
if (d === _ || e === _ || f === _) {
2016-01-13 16:19:43 +00:00
throw new Error(
'Can only use placeholder on first, second or third argument of this function.'
2017-04-19 00:55:46 +00:00
)
2015-08-12 15:35:10 +00:00
}
if (n >= 4) {
if (a === _) {
if (b === _) {
2017-04-19 00:55:46 +00:00
if (c === _) return curry3((a, b, c, e, f) => fn(a, b, c, d, e, f))
return curry2((a, b, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
if (c === _) return curry2((a, c, e, f) => fn(a, b, c, d, e, f))
return curry1((a, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
if (b === _) {
2017-04-19 00:55:46 +00:00
if (c === _) return curry2((b, c, e, f) => fn(a, b, c, d, e, f))
return curry1((b, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
if (c === _) return curry1((c, e, f) => fn(a, b, c, d, e, f))
return fn(a, b, c, d, e, f)
2015-08-12 15:35:10 +00:00
}
if (n === 3) {
if (a === _) {
2017-04-19 00:55:46 +00:00
if (b === _) return curry3((a, b, d, e, f) => fn(a, b, c, d, e, f))
return curry2((a, d, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
if (b === _) return curry2((b, d, e, f) => fn(a, b, c, d, e, f))
return curry1((d, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
if (n === 2) {
2017-04-19 00:55:46 +00:00
if (a === _) return curry3((a, c, d, e, f) => fn(a, b, c, d, e, f))
return curry2((c, d, e, f) => fn(a, b, c, d, e, f))
2015-08-12 15:35:10 +00:00
}
2017-04-19 00:55:46 +00:00
if (n === 1) return curry3((b, c, d, e, f) => fn(a, b, c, d, e, f))
return curried
}
}
export default function curry(fn, length = fn.length) {
2017-04-19 00:55:46 +00:00
return [fn, curry1, curry2, curry3, curry4][length](fn)
}