Всякий раз, когда у вас есть функция curied, вам нужен какой-то способ завершить каррирование, так же как вам нужен базовый случай для рекурсии. Это конечное условие может быть либо
(1) количество аргументов, например, 2 в этом случае:
const curry = (fn, n) => {
const c = (...args) => (...args2) => args.length + args.length >= n ? fn(...args, ...args2) : c(...args, ...args2);
return c();
};
const add = curry((a, b) => a + b, 2);
(1b) Конечно, это также можно получить из сигнатуры функций:
const curry = (fn, ...keep) => (...args) => keep.length + args.length >= fn.length ? fn(...keep, ...args) : curry(fn, ...keep, ...args);
const add = curry((a, b) => a + b);
(2) последний пустой вызов функции, например add(1, 2)()
или add(1)(2)()
const curry = fn => (...args) => (...args2) => args2.length ? curry(fn)(...args, ...args2) : fn(...args, ...args2);
const add = curry((a, b) => a + b);
(3) некоторый тип в конце, чтобы инициировать вычисляемый результат, например, +add(1, 2)
или +add(1)(2)
:
const curry = (fn, ...keep) => {
const c = (...args) => curry(fn, ...keep, ...args);
c.valueOf = () => fn(...keep);
return c;
};
const add = curry((a, b) => a + b);