multiply(10)()()()(12)
This a function call and we have to make a function to multiply 2 numbers
You can curry the function and leverage rest parameters and spreading. If there are no arguments supplied then (...args) will be an empty array and .bind(this, ...args) will create a function without partially applying any values to it.
Once all arguments are satisfied, the function is immediately called.
const curry = f => function(...args) {
if (f.length - args.length <= 0)
return f.apply(this, args);
return curry(f.bind(this, ...args));
}
const mul = (a, b) => a * b;
const multiply = curry(mul);
console.log(multiply(10, 12)); // = 120
console.log(multiply(10)(12)); // = 120
console.log(multiply(10)()(12)); // = 120
console.log(multiply(10)()()()(12)); // = 120
const obj = {
x: 2,
multiply: curry(function(a, b) {
return a * b * this.x;
})
}
console.log(obj.multiply(10)()()()(12)); // = 240
I wonder how i can convert this curry function to work with n number of variables instead of 2.
so for example i want to invoke:
curry(mul)(3)(3)(3) -> and get 27
(with a fixed version of curry)
function curry(fn) {
return function() {
if (fn.length > arguments.length) {
var slice = Array.prototype.slice;
var args = slice.apply(arguments); // get arguments as args array
return function() {
return fn.apply(null, args.concat(slice.apply(arguments)));
};
}
return fn.apply(null, arguments);
};
}
// mul is just an example it can be any function....
function mul(x, y) {
console.log(x * y)
}
curry(mul)(11)(5)
This question makes me think of food .. but you can try this version:
const curry = (fn, ...args) =>
args.length < fn.length ? (...args2) => curry(fn, ...args, ...args2) : fn(...args);
const mul = (a, b, c) => console.log(a * b * c);
curry(mul)(3)(3)(3)
curry(mul)(3, 3)(3)
curry(mul, 3, 3, 3, 3) // extra parameters are ignored by mul
IE version here https://www.typescriptlang.org/play/index.html#src=const%20curry%20%3D%20(fn...
I'm learning Javascript and wondering if it's possible to store a declared function in a variable to be used later?
For context,
function add(a, b) {
return a + b;
}
var addTogether = _.partial(add, 1);
doSomething() // returns a promise that resolves to a 2
.then(addTogether); // expect to return 3
Is there a way to achieve this?
var Add = function (a, b)
{
return a + b;
}
var result = Add (2, 3);
Absolutely. Functions ARE data in JavaScript.
var foo = function(a, b) {
return a + b;
}
Is perfectly legitimate.
function add(a, b) {
return a + b;
}
var foo = add;
console.log(foo(5,10));
console.log(add(10, 20));
You can also use ES6 syntax to store anonymous functions in constants, like so:
const add = (a, b) => a + b;
const addOne = a => add(a, 1);
console.log(add(5, 10)); // 15
console.log(addOne(5)); // 6
If f :: (a, b) -> c, we can define curry(f) as below:
curry(f) :: ((a, b) -> c) -> a -> b -> c
const curry = f => a => b => f(a, b);
const sum = curry((num1, num2) => num1 + num2);
console.log(sum(2)(3)); //5
How do we implement generic curry function that takes a function with n parameters?
If I understand correctly, I think this is the way to go using 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 fn2 = curry((a, b) => a + b);
const fn3 = curry((a, b, c) => a * (b + c));
const fn4 = curry((a, b, c, d) => Math.pow(a, b * (c + d)));
console.log(fn2(1)(2)); // 1 + 2
console.log(fn3(2)(3)(4)); // 2 * (3 + 4)
console.log(fn4(2)(1, 3)(4)); // 2 ^ (1 * (3 + 4))
If you want to do this in ES5, here's a slightly more verbose method:
function curry (f) {
var nargs = f.length;
var vargs = [];
return function curried () {
return vargs.push.apply(vargs, arguments) >= nargs
? f.apply(undefined, vargs.slice(0, nargs))
: curried;
};
}
var fn2 = curry(function (a, b) {
return a + b;
});
var fn3 = curry(function (a, b, c) {
return a * (b + c);
});
var fn4 = curry(function (a, b, c, d) {
return Math.pow(a, b * (c + d));
});
console.log(fn2(1)(2)); // 1 + 2
console.log(fn3(2)(3)(4)); // 2 * (3 + 4)
console.log(fn4(2)(1, 3)(4)); // 2 ^ (1 * (3 + 4))
Caveat: I don't have a functional background, so my terminology may be a bit off.
If by "curry" you mean "create a new function that will call the original with some arguments pre-filled," the general solution in ES5 and earlier is as follows (see comments):
// 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);
In ES2015+, we can use rest args instead of 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);
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))
There's a simple way to curry your sum function with unlimited parameters.
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());
This add function would run every time you call the curried function with another parameter. Like in the case for const six = four + two;It returns the value from two previous calls and the chain goes on and on.
Keep in mind that in order to get the primitive value we need to call .valueOf().
Below is a solution inspired by Juan Sebastián Gaitán's solution I have just extended it for below cases:
add(1, 2)(2, 3)(1, 2, 3, 4).valueOf();
add(1,2,3,4).valueOf();
add(1)(2)(3)(4)(5).valueOf();
const add = (a, ...rest) => {
a += rest.reduce((total, val) => {
return total + val;
}, 0);
const next = (...b) => add(a + b.reduce((total, val) => {
return total + val;
}, 0));
next.valueOf = () => a;
//console.log('a', a, '; next: ', next, '; rest: ', ...rest);
return next;
};
console.log(add(1, 2)(2, 3)(1, 2, 3, 4).valueOf()); //18
console.log(add(1,2,3,4).valueOf()); //10
console.log(add(1)(2)(3)(4)(5).valueOf()); //15
As the output is a function, you need valueOf(). to get the value.
the function looks little cumbersome because of .reduce() but its very simple to read.
This is a good example of recursive function and a currying function.
Lets say i have the following add function that takes an unlimited number of arguments.
function add () {
var total = 0;
var args = Array.prototype.slice.call(arguments, 0);
for (var i=0; i<args.length; i++) {
total += arguments[i];
}
return total;
}
and the following curry function.
function curryFunction(orig_func) {
var ap = Array.prototype;
var args = arguments;
function fn() {
if (arguments.length != 0) {
ap.push.apply(fn.args, arguments);
return fn;
} else {
return orig_func.apply(this, fn.args);
}
};
return function() {
fn.args = ap.slice.call( args, 1 );
return fn.apply( this, arguments );
};
}
I then want to do something like:
var f = curryFunction(add);
var a = f(3)(4)(3);
var b = f(10)(3);
var result1 = a(); // returns 10
var result2 = b(); // returns 13
However i always get 13 for both a() and b() i assume is because in line
fn.args = ap.slice.call(args, 1);
the existing array [3,4,3] is overwriting with []. Can someone please provide me with a hint on how to make this work? Thanks
The problem is that fn is scoped to curryFunction and so is shared between a and b.
All you have to do is move the definition of fn into the anonymous return function. It's then created when you call f, and the problematic fn.args = line is only called once.
Proof: jsFiddle.
Currying a function which takes indefinitely many arguments can be implemented as follows;
Lets say we have a function called addAll() which returns the sum of all provided arguments.
var addall = (...a) => a.reduce((p,c) => p + c);
And we have a curry function which takes a function and returns curried version ad infinitum up until the returned function is called with no arguments, only when the result of all previously provided arguments will be returned. OK here is the curry function.
var curry = f => (...a) => a.length ? curry(f.bind(f,...a))
: f();
Lets see it in action;
var addAll = (...a) => a.reduce((p,c) => p + c),
curry = f => (...a) => a.length ? curry(f.bind(f,...a)) : f(),
curried = curry(addAll),
result = curried(10,11)(10)(37)(10,17,42)();
console.log(result);
result = curried("a","b")("c")("d")("e","f","g")();
console.log(result);