Sitemap
The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +772K followers.

Follow publication

Variadic currying and currying to fixed arity in JavaScript

5 min readJun 28, 2020

--

I don’t need the whole world, just you

const curry = (fn) =>     
function curried(...args) {
const haveEnoughArgs = args.length >= fn.length
const partiallyApplied = (...moreArgs) =>
curried(...args.concat(moreArgs))

if (haveEnoughArgs) return fn(...args)
return partiallyApplied
}
const addInfinite = (...args) => args.reduce((acc, cur) => acc + cur, 0)
curry(addInfinite)(5) // returns 5
curry(addInfinite)() // returns 0
curryN(10, addInfinite)(5)(2)(8) // returns partially applied function
curryN(10, addInfinite)(5)(2)(8)(5)(2)(1)(8)(3)(4)(5) // returns 43
const curryN = (n, fn) =>    
function curried(...args) {
// compare to n instead of fn.length
const haveEnoughArgs = args.length >= n
const partiallyApplied = (...moreArgs) =>
curried(...args.concat(moreArgs))

if (haveEnoughArgs) return fn(...args)
return partiallyApplied
}
export const curry = (fn) => curryN(fn.length, fn)

Stop button

const addFourOrLessNumbers = (a, b, c, d) 
=> (a || 0) + (b || 0) + (c || 0) + (d || 0)
addFourOrLessNumbers(1, 2)
curry(addFourOrLessNumbers)(1, 2) // returns function
curryN(2, addFourOrLessNumbers)(1, 2) // returns 3
const addTwoOrLessNumbers = curryN(2, addTenOrLessNumbers)
const addThreeOrLessNumbers = curryN(3, addTenOrLessNumbers)
const addFourOrLessNumbers = curryN(4, addTenOrLessNumbers)
...
if (someCondition && numbers.length === 2)addTwoOrLessNumbers(...)
else if (someCondition && numbers.length === 3)
addThreeOrLessNumbers(...)
...
const curriedAddFourOrLessNumbers = curryV(addFourOrLessNumbers)
curriedAddFourOrLessNumbers(1)(3)
if (someCondition)curriedAddFourOrLessNumbers() // returns 4
const curryV = (fn) =>         
function curried(...args) {
let shouldRunRightNow = args.length === 0
const haveEnoughArgs = args.length >= fn.length
const partiallyApplied = (...moreArgs) => {
shouldRunRightNow = moreArgs.length === 0
if (shouldRunRightNow) return fn(...args)
return curried(...args.concat(moreArgs))
}

if (haveEnoughArgs || shouldRunRightNow) return fn(...args)
return partiallyApplied
}

You can just use the library

--

--

The Startup
The Startup

Published in The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +772K followers.

Ivan Korolenko
Ivan Korolenko

Written by Ivan Korolenko

https://ivankorolenko.com | Lead Frontend Engineer | Turning wishes into software

No responses yet