Skip to content

Instantly share code, notes, and snippets.

@tmatz
Created March 22, 2019 03:59
Show Gist options
  • Save tmatz/b344bc8c67c152a803a5d70ef0fc2033 to your computer and use it in GitHub Desktop.
Save tmatz/b344bc8c67c152a803a5d70ef0fc2033 to your computer and use it in GitHub Desktop.
"use strict"
const curry = fn =>
curryN(fn.length, fn)
const curryN = (n, fn) =>
rename(fn.name, (...a) => {
const num_ = count_(a)
const len = a.length - num_
return (num_ == 0 && len >= n) ?
fn(...a) :
curryN(n - len, (...b) => fn(...mergeArgs(a, b)))
})
// placeholder
const _ = Symbol()
const count_ = iter => {
let num = 0
for (const i of iter) {
if (i === _) {
num++
}
}
return num
}
// replace _ in 'a' by item of 'b'.
// if 'b' remains, concat it.
function* mergeArgs(a, b) {
const ia = a[Symbol.iterator]()
const ib = b[Symbol.iterator]()
let na = ia.next()
let nb = ib.next()
// replace '_'
while (!na.done && !nb.done) {
if (na.value === _) {
yield nb.value
nb = ib.next()
} else {
yield na.value
}
na = ia.next()
}
// rest
if (!na.done) {
yield na.value
yield* ia
}
// rest
if (!nb.done) {
yield nb.value
yield* ib
}
}
const rename = (name, fn) =>
Object.defineProperty(fn, 'name', { value: name, writable: false })
const output = []
function arg() { return arguments }
//output.push(count_(arg(1,2,_,3,_,4)))
//output.push([...mergeArgs([_,2], [1,_,3])])
const f = curry((a, b, c) => a + b + c)
// i understand the power of currying.
output.push(f(1,2,3))
output.push(f(1)(2)(3))
output.push(f(1)(2,3))
output.push(f(1,2)(3))
output.push(f(_,2,3)(1))
output.push(f(1,_,3)(2))
output.push(f(1,2,_)(3))
output.push(f(_,_,3)(1)(2))
output.push(f(_,_,3)(_,2)(1))
console.log(output
.map(JSON.stringify)
.join("\n"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment