Как вывести функцию на неизвестное количество параметров

Скажем, у меня есть функция под названием multiplyDivide

Если бы я позвонил multiplyDivide(2)(3)(4)(6) это было бы эквивалентно 2 * 3 / 4 * 6,

Обновление: возможно ли написать такую ​​функцию, если я не знаю заранее, сколько параметров я буду принимать? Например, я мог бы иметь multiplyDivide(1)(2) или же multiplyDivide(1)(2)(3)(4)...(n-1)(n)

7 ответов

Решение

Почему это должно быть карри? Разве это не было бы намного проще просто "перегрузить" функцию, предоставляя n аргументы?

function multiplyDivide() {
  var result = arguments[0];
  for (var i = 1; i < arguments.length; i++) {
    result = (i % 2) ? (result * arguments[i]) : (result / arguments[i]);
  }
  return result;
}

console.log(multiplyDivide(2, 3, 4, 6)); //9
console.log(multiplyDivide(5, 4, 2, 3, 3, 5, 1)); //50

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

Как вы сигнализируете о необходимости ценностей, зависит от вас. Один из способов сделать это - проверить, передан ли аргумент:

// Using add instead of multiplyDivide to simplify example:

function add (num) {
    function adder (n) {
        if (n !== undefined) {
            num += n;
            return adder;
        }
        else { // terminate
            return num;
        }
    }
    return adder;
}

Теперь вы можете сделать:

var sum = add(1)(2)(3)(4)();

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

var x = add(1)(2)(3)(4);
x = x(5)(6)(7);
x = x(8)(9)(10);

var sum = x();

Поскольку в js функции являются объектами, вы также можете реализовать метод получения значений как статический метод. Он не будет чисто функциональным, но сделает API более понятным и легким для чтения:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.value = function(){
        return num
    };
    return adder;
}

Что позволит вам сделать:

var sum = add(1)(2)(3)(4).value();

Вы даже можете придумать, переопределив встроенный .valueOf() а также .toString() методы:

function add (num) {
    function adder (n) {
        num += n;
        return adder;
    }
    adder.valueOf = function(){
        return num
    };
    adder.toString = function(){
        return '' + num
    };
    return adder;
}

Что позволит вам сделать:

var sum = add(1)(2)(3)(4) + 5; // results in 15
var txt = add(1)(2)(3)(4) + "hello"; // results in "10hello"

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

Вы имеете в виду что-то подобное?

var multiplyDivide = function(first){
  return function(second){
    return function(third){
      return function(forth){
        return first * second / third * forth;
      }
    }
  }
}
//should be 6
console.log(multiplyDivide(2)(4)(4)(3));
      function multiply(a) {
   return function(b) {
       return b ? multiply(a*b) : a;
   }
}

console.log(multiply(2)());
console.log(multiply(2)(3)());
console.log(multiply(2)(3)(4)());
console.log(multiply(2)(3)(4)(5)());
      function add() {
let args = [...arguments];
  function addAll(){
   let args1 = [...arguments];
   return add(...args, ...args1);
 }

let total = args.reduce((total, value) => total+value);
addAll.value = total;
return addAll;
}

console.log(add(2)(3)(4).value); 
console.log(add(2)(3).value); 

function addValues(a, b) {
   if(b!=undefined)
    return a + b;

   return function(b) {
       return a + b;
   }
}
let output1 = addValues(2)(4);  // 6
let output2 = addValues(2,1);   // 3
console.log(output1);
console.log(output2)

На самом деле это очень хороший вопрос...

Карринг является одним из самых фундаментальных аспектов функциональных языков программирования, где вы можете передавать и возвращать функции. JS, являющийся функциональным языком программирования на каком-то уровне, должен уметь выполнять эту операцию.

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

ОК, пусть ваша функция будет

function multiplyDivide (n,m,o,p){
  return n * m / o * p;
}

Тогда способ реализации утилиты curry Функция для получения карри версии любой данной функции будет выглядеть следующим образом;

var curry = f => f.length ? (...a) => curry(f.bind(f,...a)) : f(),

Итак, давайте посмотрим на это в действии

function multiplyDivide (n,m,o,p){
      return n * m / o * p;
    }

var curry = f => f.length ? (...a) => curry(f.bind(f,...a)) : f(),
    f     = curry(multiplyDivide);
 
 res1 = f(4,5,2,10),
 res2 = f(4)(5,2,10),
 res3 = f(4)(5)(2,10),
 res4 = f(4)(5)(2)(10),
 res5 = f(4,5)(2,10),
 res6 = f(4,5)(2)(10),
 res7 = f(4,5,2)(10),
 res8 = f(4,5)(2,10);
console.log(res1,res2,res3,res4,res5,res6,res7,res8);

Там могут быть более простые способы, но это то, что я мог придумать.

Другие вопросы по тегам