how does javascript currying function actually works? - javascript

i've been having a lot of trouble understand how this currying function actually works
and what exactly its doing ?
Function.prototype.curry = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
because im only familiar with this type of currying function:
function curry(f) {
return function(a) {
return function(b) {
return f(a, b);
};
}

Related

Why does the default JS bind function works and why my polyfill for the bind returns undefined?

I am trying to write the polyfill for the js bind function over a multiply function. The js bind function is giving the correct answer 8 but my polyfill is giving undefined. The main multiply function is returning all the params correctly though.
Function.prototype.myBind = function (...args) {
let obj = this;
let params = args.slice(1);
return function (...param2) {
obj.apply(args[0], [...params, ...param2]);
};
};
let mul = (a, b) => {
console.log(13, a, b, a * b);
return a * b;
};
let mulFour = mul.bind(this, 4);
let myMulFour = mul.myBind(this, 4);
console.log(mulFour(2));
console.log(myMulFour(2));
CertainPerformance was correct, needed to return the obj.apply(args[0], [...params, ...param2]); again.
The polyfill would go like this:
Function.prototype.myBind = function (...args) {
let obj = this;
let params = args.slice(1);
return function (...param2) {
return obj.apply(args[0], [...params, ...param2]);
};
};

Finding the sum of a curry function?

var curry = function (func) {
return function (a) {
return function (b) {
return function (c) {
return function (d) {
return function (e) {
return func (a, b, c, d, e);
}
}
}
}
}
}
var getSum=curry(a+b+c+d+e);
console.log(getSum(15)(20)(25)(30)(35));
This is my code so far, but it's saying a is not defined and I'm not sure how to fix it. If I do this with Math.max it works, how can I achieve the same thing but with a sum instead of max?
By defining a function that sums its arguments, just like Math.max finds the max of its arguments:
const curry = function (func) {
return function (a) {
return function (b) {
return function (c) {
return function (d) {
return function (e) {
return func (a, b, c, d, e);
};
};
};
};
};
};
const getSum = (...args) => {
return args.reduce((sum, value) => sum + value, 0);
};
console.log(curry(getSum)(15)(20)(25)(30)(35));
Curry is expecting a function with your decleration
var curry = function (func) {...}
You should be calling it with a function. However you're attempting to resolving some variables and add them then just pass the number. What you have here is a Higher Order Function, or a Function which takes a Function and returns a Function.
var getSum=curry(a+b+c+d+e); // not passing a function
Your code however is attempting to do the following:
var temp = a+b+c+d+e;
var getSum=curry(temp);
The problem is that now it's attempting to find a global a, b, c, d, and e variable, to sum them, and then pass that to curry... which fails as soon as it tries to find a global a. What you want to pass is a function.
var getSum = curry((...arg) => args.reduce((acc, value) => acc + value));
This is a function that takes a variable amount of arguments, so when you pass it to curry it will return a function(a internal to curry scope), which when called will return a function(b to a scope) which will return a fun.... so on and so forth until it finally calls the last time and sums them all after the last call.
Another more advanced version of an automatic curry function with examples from 30 Seconds of Code
const curry = (fn, arity = fn.length, ...args) =>
arity <= args.length ? fn(...args) : curry.bind(null, fn, arity, ...args);
curry(Math.pow)(2)(10); // 1024
curry(Math.min, 3)(10)(50)(2); // 2
Other versions of Curry exist in other places like RamdaJS, but you get the idea. It's a higher order function that continuously returns functions until you've supplied enough arguments to satisfy it's arity(how many arguments it wants).
You need to supply a function for the five parameters and take the function for the first call of curry.
var curry = function(func) {
return function(a) {
return function(b) {
return function(c) {
return function(d) {
return function(e) {
return func(a, b, c, d, e);
}
}
}
}
}
}
var getSum = function (a, b, c, d, e) { return a + b + c + d + e; };
console.log(curry(getSum)(15)(20)(25)(30)(35));
A dynamic approach without binding.
var curry = fn => {
const
curried = p => (...args) => {
p = [...p, ...args];
return p.length < fn.length
? curried(p)
: fn(...p);
};
return curried([]);
},
getSum = (a, b, c, d, e) => a + b + c + d + e;
console.log(curry(getSum)(15)(20)(25)(30)(35));
var add = curry((a, b, c, d) => a + b + c + d),
add1 = add(1),
add2 = add(2)(3)(4);
console.log(add1() === 10); // false
A dynamic approach for curry function. Here What I have done is curry function takes the function to be curried func returns a new function temp.
Inside temp we check if length of arguments of temp is less than the number of arguments required for the original function func.
If it is less we return temp again with the arguments received, else call the original function func with all the arguments
var getSum = function (a, b, c, d, e) { return a + b + c + d + e; };
function curry(func){
return function temp(...args) {
if (args.length < func.length) {
return temp.bind(null, ...args)
}
return func(...args)
}
}
console.log(curry(getSum)(15)(20)(25)(30)(35));

Is it possible to create sum function from reduce and curry without inline functions?

I want to create function sum out of curry and reduce if I have standard functions apply and call:
My try:
// those are init functions:
function type(label, arg, type) {
// some type checking so you know which function
// throw exception and why
var arg_type;
if (arg instanceof Array) {
arg_type = 'array';
} else if (arg === null) {
arg_type = 'null';
} else {
arg_type = typeof arg;
}
if (arg_type !== type) {
throw new Error(`${label}: Expecting ${type} got ${arg_type}`);
}
}
function curry(fn, ...init_args) {
type('curry', fn, 'function');
var len = fn.length;
return function() {
var args = init_args.slice();
function call(...more_args) {
args = args.concat(more_args);
//console.log({fn, len, args});
if (args.length >= len) {
return fn.apply(this, args);
} else {
return call;
}
}
return call.apply(this, arguments);
};
}
function reduce(fn, init, ...lists) {
if (lists.some(l => !l.length)) {
return init;
}
type('reduce', fn, 'function');
lists.forEach(a => type('reduce', a, 'array'));
const head = lists.map(l => l[0]);
const rest = lists.map(l => l.slice(1));
return reduce(fn, fn(...head, init), ...rest);
}
function apply(fn, args) {
type('apply', fn, 'function');
type('apply', args, 'array');
return fn.apply(null, args);
}
function call(fn, ...args) {
type('call', fn, 'function');
return fn.call(null, ...args);
}
var add = (a, b) => a + b;
// and this only using those without new inline function
var sum = curry(call, curry(reduce, add));
console.log(sum(1, 2, 3, 4));
var sum = curry(apply, curry(reduce, add));
console.log(sum(1, 2, 3, 4));
Is it possible to create sum function with: curry, apply, reduce and/or call? If not is it possible to add some generic known function that will allow to create sum without inline functions (this include arrow functions)?
I can create sum functions like this:
var sum = (...args) => reduce(add, 0, args);
so it seems what I need is function that get list of arguments and call function as array.
function caller(fn, ...args) {
return fn.call(null, args);
}
var sum = curry(caller, curry(reduce, add, 0));
console.log(curry(reduce, add, 0)([1,2,3,4]));
console.log(sum(1, 2, 3, 4));
function spread(fn) {
return function(...args) {
return call(fn, args);
};
}
var sum = spread(curry(reduce, add, 0));
console.log(sum(1, 2, 3, 4));
Does functions like caller and spread have some common name? Or is there a better way to create sum function, with those requirement? I can also use pipe or compose functions because they are also common, not sure if you can use them to create sum.
So basically my question is this, is possible to create sum function using any known function in functional libraries without any inline functions? Builtin functions like bind are also allowed.
This can be generalized to create a function from function two arguments that can be called with any arguments and it reduce on each argument without using inline function.
I want to know this because I want to know more about function programming.
I have no idea what you mean by inline functions.
But:
function ad = (a, b) => a + b;
function sum (...args) {
return args.reduce(add, 0);
}
console.log(sum(1, 2, 3, 4));
EDIT: Didn't understand the original question, here is the answer
// From lodash, is named differently in other FP libraries
const partialRight = (func, ...boundArgs) => (...remainingArgs) =>
func(...remainingArgs, ...boundArgs);
// From Lodash
const rest = (fn) => (...args) => fn(args);
// From any FP library
const reduce = function(iterable, reduceFn, accumulator){
for(let i of iterable){
accumulator = reduceFn(accumulator, i)
}
return accumulator
}
const add = (a, b) => a + b;
const sum = rest(partialRight(reduce, add, 0));
console.log(sum(1, 2, 3, 4));

Convert functional js function to general case

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...

Javascript Object or new function for function handler

I am a bit confused as which one of the following is the right way to create a handler containing functions...An object with function or a new function itself?
Say, a handler for calculator functions...
CalculatorHandler = new function(){
this.add = new function(a, b){
return a + b;
};
this.sub = new function(a, b){
return a-b;
};
};
Or
CalculatorHandler = {
this.add: function(a, b){
return a + b;
},
this.sub: function(a, b){
return a-b;
}
};
Are there any advantage/disadvantage of one over the other?
If you just want to have a "basket" to hold your functions together, simply use an object, there is no need for a constructor function:
CalculatorHandler = {
add: function(a, b){
return a + b;
},
sub: function(a, b){
return a-b;
}
};
Note how the this in your example is incorrect as it will refer to the scope you define the CalculatorHandler object in (probably global - window).
On the other hand if you want to build a calculator to have some data and do operations on it, then you can use the OOP-like approach in your first example.
CalculatorHandler = function() {
this.total=0;
this.add = function(a) {
this.total += a;
};
this.sub = function(a) {
this.total -= a;
};
}
var calc = new CalculatorHandler();
calc.add(4);
calc.sub(3);
And a better solution, based on prototipal inheritance:
CalculatorHandler = function() {
this.total=0;
}
CalculatorHandler.prototype.add = function(num) {
this.total += num;
}
CalculatorHandler.prototype.sub = function(num) {
this.total -= num;
};
var calc = new CalculatorHandler();
calc.add(4);
calc.sub(3);

Categories

Resources