2017-02-05 95 views
4

Вопрос: Как бы вы сделали эту работу?
добавить (2) (5); // 7
добавить (2, 5); // 7Сделать функцию, поддерживающую каррирование И традиционные многочисленные параметры

Я пытаюсь решить вопрос выше: Я знаю, что первое решение использует выделки и будет осуществляться следующим образом:

var add = functoin(x){ 
return function (y){ 
return x+y; 
}; 
}; 

в то время как второй является вашей обычной этого нужно просто функции:

var add = functoin(x,y){ 
return x+y; 
}; 

Есть ли способ заставить обе работать одновременно?

ответ

2

Вы можете использовать функцию высшего порядка, чтобы обернуть другие функции с тем, что поведение.

Этот вид функции часто называют curry, и он поставляется со многими библиотеками (например, lodash).

curry возвращает новую функцию, которая проверяет, были ли предоставлены все ожидаемые аргументы. Если они есть, он вызывает originalFunction. Если нет, он возвращает частично прикладную функцию,

В этой реализации используется Function#length для проверки вероятности вызова, поэтому она работает с любым количеством аргументов.

function curry (fn) { 
 
    return function (...args) { 
 
    if (args.length >= fn.length) { 
 
     return fn.call(this, ...args) 
 
    } else { 
 
     return curry(fn.bind(this, ...args)) 
 
    } 
 
    } 
 
} 
 

 
function add (x, y) { 
 
    return x + y; 
 
} 
 

 
// You can curry any function! 
 
const curriedAdd = curry(add); 
 

 
console.log(curriedAdd(1, 2)); // 3 
 
console.log(curriedAdd(1)(2)); // 3 
 
console.log(curriedAdd(1)); // a function

+1

Имейте в виду, что 'Function # length' не включает необязательные аргументы, и эта реализация не делает ничего особенного, чтобы помочь с этим, - как обычно, оно определяется тем, как вызывается функция curried. – joews

+1

Если вы хотите сделать реальную currying, которая работает для более чем 2 параметров, вы должны сделать 'return curry (fn.bind (null, ... args))' – Bergi

+0

@Bergi спасибо, вот что я имел в виду :-) – joews

2

Вы можете проверить количество аргументов, переданных в и вернуть один или либо в зависимости от этого:

function add(a, b) { 
 
    if (arguments.length == 2) { 
 
    return a + b; 
 
    } 
 
    return function(b) { 
 
    return add(a, b); 
 
    } 
 
} 
 

 
console.log(add(2)(5)); // 7 
 
console.log(add(2, 5)); // 7

+0

Лучше: 'функция (б) {возвращение добавить (а, б); } ', так что вам не нужно дублировать код – Bergi

+0

@Bergi yup, у меня на самом деле было то, что сначала было переключено, так как я понял, что это проще, без рекурсии. Теперь переключился. – nem035