2016-07-28 7 views
0

Если F :: (а, Ь) -> с, мы можем определить Карри (е), как показано ниже:Карринг в JavaScript для функции с п параметров

Карри (е) :: ((а, б) -> с) -> а -> Ь -> с

const curry = f => a => b => f(a, b); 
const sum = curry((num1, num2) => num1 + num2); 
console.log(sum(2)(3)); //5 

Как мы реализуем обобщенную функцию карри, которая принимает функцию с параметрами п?

+0

Вы имеете в виду 'f :: ((a, b) -> c) -> (a-> b-> c)'? –

+0

@Patrick Roberts yes –

+1

Мне нравятся эти проблемы с карри. Я должен написать библиотеку или что-то с кучей утилит currying, может быть, люди сочтут это целесообразным. –

ответ

3

Если я правильно понимаю, я думаю, что это путь, используя ES6:

const curry = f => { 
 
    const nargs = f.length; 
 
    const vargs = []; 
 
    const curried = (...args) => vargs.push(...args) >= nargs ? f(...vargs.slice(0, nargs)) : curried; 
 
    
 
    return curried; 
 
}; 
 

 
const arg2 = curry((a, b) => a + b); 
 
const arg3 = curry((a, b, c) => a * (b + c)); 
 
const arg4 = curry((a, b, c, d) => Math.pow(a, b * (c + d))); 
 

 
console.log(arg2(1)(2)); // 1 + 2 
 
console.log(arg3(2)(3)(4)); // 2 * (3 + 4) 
 
console.log(arg4(2)(1, 3)(4)); // 2^(1 * (3 + 4))

Если вы хотите сделать это в ES5, вот немного более многословным метод :

function curry(f) { 
 
    var nargs = f.length; 
 
    var vargs = []; 
 
    
 
    return function curried() { 
 
    var args = Array.prototype.slice.call(arguments); 
 

 
    return vargs.push.apply(vargs, args) >= nargs ? f.apply(this, vargs.slice(0, nargs)) : curried; 
 
    }; 
 
} 
 

 
var arg2 = curry(function (a, b) { 
 
    return a + b; 
 
}); 
 
var arg3 = curry(function (a, b, c) { 
 
    return a * (b + c); 
 
}); 
 
var arg4 = curry(function (a, b, c, d) { 
 
    return Math.pow(a, b * (c + d)); 
 
}); 
 

 
console.log(arg2(1)(2)); // 1 + 2 
 
console.log(arg3(2)(3)(4)); // 2 * (3 + 4) 
 
console.log(arg4(2)(1, 3)(4)); // 2^(1 * (3 + 4))

+0

@Patrick Roberts Ваша реализация действительно короткая. –

+1

@PatrickRoberts: Га, я [смотрел здесь] (http://www.ecma-international.org/ecma-262/7.0/index.html#sec-functioninitialize) и неправильно читал «перечислимый» как «настраиваемый». Отлично, что делает вещи ** много ** проще. –

+1

@ T.J.Crowder проверить мое обновление;) –

2

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

Если под «Карри» вы имеете в виду «создать новую функцию, которая будет вызывать оригинал с некоторыми аргументами предварительно заполненных,» общее решение в ES5 и ранее, следующим образом (см комментарии):

// Add a function to the function prototype 
 
Object.defineProperty(Function.prototype, "curry", { 
 
    value: function() { 
 
    // Remember the original function 
 
    var f = this; 
 
    // Remember the curried arguments 
 
    var args = Array.prototype.slice.call(arguments); 
 
    // Return a new function that will do the work 
 
    return function() { 
 
     // The new function has been called: Call the original with 
 
     // the curried arguments followed by any arguments received in 
 
     // this call, passing along the current value of `this` 
 
     return f.apply(this, args.concat(Array.prototype.slice.call(arguments))); 
 
    }; 
 
    } 
 
}); 
 

 
// Usage: 
 
function foo(a, b, c) { 
 
    console.log(a, b, c); 
 
} 
 
var f = foo.curry(1, 2); 
 
f(3);

В ES2015 +, мы можем использовать отдыха арг вместо arguments:

// REQUIRES ES2015+ support in your browser! 
 

 
// Add a function to the function prototype 
 
Object.defineProperty(Function.prototype, "curry", { 
 
    value: function(...curriedArgs) { 
 
    // Remember the original function 
 
    let f = this; 
 
    // Return a new function that will do the work 
 
    return function(...args) { 
 
     // The new function has been called: Call the original with 
 
     // the curried arguments followed by any arguments received in 
 
     // this call, passing along the current value of `this` 
 
     return f.apply(this, curriedArgs.concat(args)); 
 
    }; 
 
    } 
 
}); 
 

 
// Usage: 
 
function foo(a, b, c) { 
 
    console.log(a, b, c); 
 
} 
 
let f = foo.curry(1, 2); 
 
f(3);

+0

Извинения, отсутствовал ')', не заметил, пока я не добавил фрагменты. –

+0

Я думаю, что мы интерпретировали вопрос разными способами, я думаю, мы увидим, чья интерпретация была правильной: P –

+0

@PatrickRoberts: Действительно! :-) Они оба хорошо отвечают на вопрос, на который они отвечают, посмотрим, что ответит на вопрос OP. –

0

ES6/2015

const curry = fn => function curried(cargs) { 
 
    return cargs.length >= fn.length ? fn.apply(this, cargs) : (...args) => curried([...cargs, ...args]) 
 
}([]); 
 

 
const arg2 = curry((a, b) => a + b); 
 
const arg3 = curry((a, b, c) => a * (b + c)); 
 
const arg4 = curry((a, b, c, d) => Math.pow(a, b * (c + d))); 
 

 
console.log(arg2(1)(2)); // 1 + 2 
 
console.log(arg3(2)(3)(4)); // 2 * (3 + 4) 
 
console.log(arg4(2)(1, 3)(4)); // 2^(1 * (3 + 4))

ES5

var curry = function(fn) { 
 
    var args = Array.prototype.slice.call(arguments); 
 
    if (args.length - 1 >= fn.length) return fn.apply(this, args.slice(1)); 
 
    return function() { 
 
    return curry.apply(this, args.concat.apply(args, arguments)); 
 
    }; 
 
}; 
 

 
var arg2 = curry(function(a, b) { 
 
    return a + b; 
 
}); 
 
var arg3 = curry(function(a, b, c) { 
 
    return a * (b + c); 
 
}); 
 
var arg4 = curry(function(a, b, c, d) { 
 
    return Math.pow(a, b * (c + d)); 
 
}); 
 

 
console.log(arg2(1)(2)); // 1 + 2 
 
console.log(arg3(2)(3)(4)); // 2 * (3 + 4) 
 
console.log(arg4(2)(1, 3)(4)); // 2^(1 * (3 + 4))

0

Там простой способ, чтобы снискать вашу sum функцию остроумие h неограниченные параметры.

const add = (a) => { 
 
    const next = b => add(a + b); 
 
    next.valueOf =() => a 
 
    return next; 
 
}; 
 

 
const one = add(1); 
 
console.log(one.valueOf()); 
 

 
const two = one + 1; 
 
console.log(two); 
 

 
const four = two + two; 
 
console.log(four) 
 

 
const six = add(four)(two); 
 
console.log(six.valueOf()); 
 

 
const eleven = six(4)(1); 
 
console.log(eleven.valueOf());

Эта add функция будет работать каждый раз, когда вы называете выделанной функцию с другим параметром. Как и в случае для const six = four + two; Он возвращает значение из двух предыдущих вызовов, и цепочка продолжается и продолжается.

Имейте в виду, что для получения примитивного значения нам необходимо позвонить .valueOf().

 Смежные вопросы

  • Нет связанных вопросов^_^