Write curry(fn) so that sum(1)(2)(3), sum(1,2)(3) and sum(1,2,3) all work for a 3-arg fn.
Closures + fn.length + recursion. Tests functional-programming fluency.
Collect arguments across calls. If we've gathered at least fn.length args, invoke; otherwise return a function that keeps collecting. fn.length gives the expected arity. This is closures capturing accumulated args. Each partial call returns a new function that closes over the args gathered so far, so the accumulation is immutable per branch — sum(1) and sum(2) don't interfere. fn.length counts only parameters before the first default/rest parameter, so currying a variadic function (...args) reports arity 0 and fires immediately; for those you need an explicit arity argument. Currying (one arg at a time) is a special case of partial application (fix any number of args up front); both trade generality for reusable, pre-configured functions and enable point-free composition.
Building reusable specialized functions, point-free pipelines, partial application of config.