Skip to content

Instantly share code, notes, and snippets.

@brianneisler
Created January 21, 2019 00:51
Show Gist options
  • Save brianneisler/c747c9056754aedc4f59c5d53b2ed2bb to your computer and use it in GitHub Desktop.
Save brianneisler/c747c9056754aedc4f59c5d53b2ed2bb to your computer and use it in GitHub Desktop.
functionCurryN
const functionCurry1 = (func) => {
return function f1(arg0, ...rest) {
if (arguments.length === 0) {
throw new Error('curried method called with no arguments')
}
if (anyIsPlaceholder(arg0)) {
if (rest.length > 0) {
throw new Error('use of a placeholder with additional arguments is not supported')
}
return f1
}
// functionValidateArg(arg0, 0, func)
return func.apply(this, arguments)
}
}
const functionCurry2 = (fn) => {
return function f2(a, b) {
switch (arguments.length) {
case 0:
throw new Error('curried method called with no arguments')
case 1:
return anyIsPlaceholder(a)
? f2
: functionCurry1(function(_b) {
return fn(a, _b)
})
default:
return anyIsPlaceholder(a) && anyIsPlaceholder(b)
? f2
: anyIsPlaceholder(a)
? functionCurry1(function(_a) {
return fn(_a, b)
})
: anyIsPlaceholder(b)
? functionCurry1(function(_b) {
return fn(a, _b)
})
: fn(a, b)
}
}
}
const functionCurry3 = (fn) => {
return function f3(a, b, c) {
switch (arguments.length) {
case 0:
throw new Error('curried method called with no arguments')
case 1:
return anyIsPlaceholder(a)
? f3
: functionCurry2(function(_b, _c) {
return fn(a, _b, _c)
})
case 2:
return anyIsPlaceholder(a) && anyIsPlaceholder(b)
? f3
: anyIsPlaceholder(a)
? functionCurry2(function(_a, _c) {
return fn(_a, b, _c)
})
: anyIsPlaceholder(b)
? functionCurry2(function(_b, _c) {
return fn(a, _b, _c)
})
: functionCurry1(function(_c) {
return fn(a, b, _c)
})
default:
return anyIsPlaceholder(a) && anyIsPlaceholder(b) && anyIsPlaceholder(c)
? f3
: anyIsPlaceholder(a) && anyIsPlaceholder(b)
? functionCurry2(function(_a, _b) {
return fn(_a, _b, c)
})
: anyIsPlaceholder(a) && anyIsPlaceholder(c)
? functionCurry2(function(_a, _c) {
return fn(_a, b, _c)
})
: anyIsPlaceholder(b) && anyIsPlaceholder(c)
? functionCurry2(function(_b, _c) {
return fn(a, _b, _c)
})
: anyIsPlaceholder(a)
? functionCurry1(function(_a) {
return fn(_a, b, c)
})
: anyIsPlaceholder(b)
? functionCurry1(function(_b) {
return fn(a, _b, c)
})
: anyIsPlaceholder(c)
? functionCurry1(function(_c) {
return fn(a, b, _c)
})
: fn(a, b, c)
}
}
}
const functionCurryN = (fn, length, received = []) => {
if (length <= 0) {
throw new TypeError('functionCurryN method expects length to be greater than 0')
}
if (received.length === 0) {
switch (length) {
case 1:
return functionCurry1(fn)
case 2:
return functionCurry2(fn)
case 3:
return functionCurry3(fn)
}
}
return function() {
const combined = []
let argsIdx = 0
let left = length
let combinedIdx = 0
while (combinedIdx < received.length || argsIdx < arguments.length) {
let result
if (
combinedIdx < received.length &&
(!anyIsPlaceholder(received[combinedIdx]) || argsIdx >= arguments.length)
) {
result = received[combinedIdx]
} else {
result = arguments[argsIdx]
argsIdx += 1
}
combined[combinedIdx] = result
if (!anyIsPlaceholder(result)) {
left -= 1
}
combinedIdx += 1
}
return left <= 0
? fn.apply(this, combined)
: functionArity(functionCurryN(fn, length, combined), left)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment