Javascript functional programming quiz - javascript

Here is the problem. I have to implement make function:
var sum = function (a, b) { return a + b; }
var mult = function (a, b) { return a * b; }
//'make' function goes here
var res = make(1)(2)(3)(4);
console.log(res(sum)); //OUTPUT: 10
console.log(res(mult)); //OUTPUT: 24
I have implemented it, but I feel like a little better way still exists. :)
So, here is my solution:
function make(a, arr) {
if (a instanceof Function) { return arr.reduce(a); }
arr = arr || [];
arr.push(a);
return function (b) { return make(b, arr); };
}

You want functions? You can have functions!
function sum(a, b) { return a + b; }
function mult(a, b) { return a * b; }
function diff(a, b) { return a - b; }
function make(x, f) {
if (typeof x === 'function') return f(x);
return function(y) {
return make(y, function(a) {
return f ? a(f(a), x) : x;
});
};
}
console.log(make(1)(2)(3)(4)(sum)); // -> 10
console.log(make(1)(2)(3)(4)(mult)); // -> 24
console.log(make(4)(3)(2)(1)(diff)); // -> -2
Instead of building up an array, this builds up a function that, when given a function, reduces all the elements using that function, from left to right :)
I'm pretty sure this wouldn't qualify as code that anyone would ever want to see in their codebase.

function make(inp, arr) {
if (typeof inp == 'function') {
while(arr.length > 1)
arr.push(inp(arr.pop(), arr.pop()));
return arr[0];
}
if (!arr) arr = [];
arr.push(inp);
return function (inp1) {
return make(inp1, arr);
};
}

Here's a better JavaScript specific solution:
var test = make(1)(2)(3)(4);
alert(test(add)); // ((1 + 2) + 3) + 4 = 10
alert(test(mul)); // ((1 * 2) * 3) * 4 = 24
alert(test(sub)); // ((1 - 2) - 3) - 4 = -8
function make(x) {
if (typeof x !== "function") return foldl([x]);
throw new TypeError("Initial value can't be a function");
}
function foldl(array) {
return function (fx) {
return typeof fx !== "function" ?
foldl(array.concat(fx)) :
array.reduce(fx);
};
}
function add(a, b) { return a + b; }
function mul(a, b) { return a * b; }
function sub(a, b) { return a - b; }
There are several advantages to this method:
Better error reporting when you write incorrect code like make(add).
Simple functional definition which is easy to read and understand.
If you want foldr then just rename reduce to reduceRight.
Using concat instead of push to preserve original array.
I can't think of a better functional implementation for make.

Related

I am trying to use arguments of one function to another as a prarmeter ,using .bind

Hello there i am here trying to use the arguments of one function to parameters of another function.What i am doing here is?I am passing a score for both a and b that results to win or loose with the score i give as a argument,now i want to use that arguments to print out total score for me ,using .bind method.
var club = {
score : function(a,b){
if (a>b){
return ('win');
}
else if (a<b){
return ('lose');
}
}
}
var germann = function(a,b,c){
console.log('yourmatch is: '+this.score(a,b));
};
var germannteam = germann.bind(club);
germannteam(4,2);
So now what can i do to get print out as total of (4,2) = 6
you can add a method to club which do the calculation for this object and return the total
var club = {
score: function(a, b) {
if (a > b) {
return ('win');
} else if (a < b) {
return ('lose');
} else {
return 'equality';
}
},
total: function(a, b) {
return (a > b) ? a + b : (a < b) ? a - b : 0;
}
}
var germann = function(a, b, c) {
console.log('yourmatch is: ' + this.score(a, b));
console.log('your score is: ' + this.total(a, b));
};
var germannteam = germann.bind(club);
germannteam(2, 4);
germannteam(4, 2);
germannteam(4, 4);

How to write a function which can accept one or more arguments and send back addition

I have to call function in below way
sum(3)(2)
My function is:
sum(a,b) { return a + b }
Take a look at Currying concept
let sum = (a) => (b) => a + b
console.log(sum(1)(3)) // 4
you can try out this approach
function sum(x, y) {
if (y !== undefined) {
return x + y;
} else {
return function(y) { return x + y; };
}
}
To understand it better https://www.toptal.com/javascript/interview-questions

TypeError: func(...).then is not a function

I am a beginner of JavaScript. I am trying to understand the functions and promises in JS. I wrote a small code.
code Purpose: I wrote this code to understand the working of promise function(then) on function with a return value.
input: a,b
output: if the sum of a & b is 0, then show the alert statement else show sum in the alert value.
const func = (a, b) => {
let operand1 = a * 10;
let operand2 = b * 10;
return operand1 + operand2
};
const funcwrapper = (a, b) => {
func(a, b).then((sum) => {
if (sum == 0) {
window.alert("value is zero");
} else {
window.alert(("sum is " + sum));
}
})
};
funcwrapper(5, 5);
I am still confused with this promise on functions with some return value after going through lot of investigation. So finally tried to implement the code to understand and got stuck with this error.
Please help me in understanding this topic.
Your help is appreciated.
Thanks in advance
func() needs to return a promise:
const func = (a, b) => {
let operand1 = a * 10;
let operand2 = b * 10;
return new Promise((resolve, reject) => resolve(operand1 + operand2));
};
const funcwrapper = (a, b) => {
func(a, b).then((sum) => {
if (sum == 0) {
window.alert("value is zero");
} else {
window.alert(("sum is " + sum));
}
})
};
funcwrapper(5, 5);

JS function which can work with 2 different invocations.

How to define a function lets say 'add' in Javascript, that will support both of these invocations.
add(5,6)
or
add(5)(6)
both giving the same output, which is 11.
function add(a, b)
if (typeof(b) === "undefined") {
return function (b) { return a + b; };
}
return a + b;
}
or, the logical extension:
function add(a, b)
if (typeof(b) === "undefined") {
return function (b) { return a + b; };
}
return add(a)(b);
}

Variadic curried sum function

I need a js sum function to work like this:
sum(1)(2) = 3
sum(1)(2)(3) = 6
sum(1)(2)(3)(4) = 10
etc.
I heard it can't be done. But heard that if adding + in front of sum can be done.
Like +sum(1)(2)(3)(4). Any ideas of how to do this?
Not sure if I understood what you want, but
function sum(n) {
var v = function(x) {
return sum(n + x);
};
v.valueOf = v.toString = function() {
return n;
};
return v;
}
console.log(+sum(1)(2)(3)(4));
JsFiddle
This is an example of using empty brackets in the last call as a close key (from my last interview):
sum(1)(4)(66)(35)(0)()
function sum(firstNumber) {
let accumulator = firstNumber;
return function adder(nextNumber) {
if (nextNumber === undefined) {
return accumulator;
}
accumulator += nextNumber;
return adder;
}
}
console.log(sum(1)(4)(66)(35)(0)());
I'm posting this revision as its own post since I apparently don't have enough reputation yet to just leave it as a comment. This is a revision of #Rafael 's excellent solution.
function sum (n) {
var v = x => sum (n + x);
v.valueOf = () => n;
return v;
}
console.log( +sum(1)(2)(3)(4) ); //10
I didn't see a reason to keep the v.toString bit, as it didn't seem necessary. If I erred in doing so, please let me know in the comments why v.toString is required (it passed my tests fine without it). Converted the rest of the anonymous functions to arrow functions for ease of reading.
New ES6 way and is concise.
You have to pass empty () at the end when you want to terminate the call and get the final value.
const sum= x => y => (y !== undefined) ? sum(x + y) : x;
call it like this -
sum(10)(30)(45)();
Here is a solution that uses ES6 and toString, similar to #Vemba
function add(a) {
let curry = (b) => {
a += b
return curry
}
curry.toString = () => a
return curry
}
console.log(add(1))
console.log(add(1)(2))
console.log(add(1)(2)(3))
console.log(add(1)(2)(3)(4))
Another slightly shorter approach:
const sum = a => b => b? sum(a + b) : a;
console.log(
sum(1)(2)(),
sum(3)(4)(5)()
);
Here's a solution with a generic variadic curry function in ES6 Javascript, with the caveat that a final () is needed to invoke the arguments:
const curry = (f) =>
(...args) => args.length? curry(f.bind(0, ...args)): f();
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1)() == 5 // true
Here's another one that doesn't need (), using valueOf as in #rafael's answer. I feel like using valueOf in this way (or perhaps at all) is very confusing to people reading your code, but each to their own.
The toString in that answer is unnecessary. Internally, when javascript performs a type coersion it always calls valueOf() before calling toString().
// invokes a function if it is used as a value
const autoInvoke = (f) => Object.assign(f, { valueOf: f } );
const curry = autoInvoke((f) =>
(...args) => args.length? autoInvoke(curry(f.bind(0, ...args))): f());
const sum = (...values) => values.reduce((total, current) => total + current, 0)
curry(sum)(2)(2)(1) + 0 == 5 // true
Try this
function sum (...args) {
return Object.assign(
sum.bind(null, ...args),
{ valueOf: () => args.reduce((a, c) => a + c, 0) }
)
}
console.log(+sum(1)(2)(3,2,1)(16))
Here you can see a medium post about carried functions with unlimited arguments
https://medium.com/#seenarowhani95/infinite-currying-in-javascript-38400827e581
Try this, this is more flexible to handle any type of input. You can pass any number of params and any number of paranthesis.
function add(...args) {
function b(...arg) {
if (arg.length > 0) {
return add(...[...arg, ...args]);
}
return [...args, ...arg].reduce((prev,next)=>prev + next);
}
b.toString = function() {
return [...args].reduce((prev,next)=>prev + next);
}
return b;
}
// Examples
console.log(add(1)(2)(3, 3)());
console.log(+add(1)(2)(3)); // 6
console.log(+add(1)(2, 3)(4)(5, 6, 7)); // 28
console.log(+add(2, 3, 4, 5)(1)()); // 15
Here's a more generic solution that would work for non-unary params as well:
const sum = function (...args) {
let total = args.reduce((acc, arg) => acc+arg, 0)
function add (...args2) {
if (args2.length) {
total = args2.reduce((acc, arg) => acc+arg, total)
return add
}
return total
}
return add
}
document.write( sum(1)(2)() , '<br/>') // with unary params
document.write( sum(1,2)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)() , '<br/>') // with unary params
document.write( sum(1)(2,3)() , '<br/>') // with binary params
document.write( sum(1)(2)(3)(4)() , '<br/>') // with unary params
document.write( sum(1)(2,3,4)() , '<br/>') // with ternary params
ES6 way to solve the infinite currying. Here the function sum will return the sum of all the numbers passed in the params:
const sum = a => b => b ? sum(a + b) : a
sum(1)(2)(3)(4)(5)() // 15
function add(a) {
let curry = (b) => {
a += b
return curry;
}
curry[Symbol.toPrimitive] = (hint) => {
return a;
}
return curry
}
console.log(+add(1)(2)(3)(4)(5)); // 15
console.log(+add(6)(6)(6)); // 18
console.log(+add(7)(0)); // 7
console.log(+add(0)); // 0
Here is another functional way using an iterative process
const sum = (num, acc = 0) => {
if !(typeof num === 'number') return acc;
return x => sum(x, acc + num)
}
sum(1)(2)(3)()
and one-line
const sum = (num, acc = 0) => !(typeof num === 'number') ? acc : x => sum(x, acc + num)
sum(1)(2)(3)()
You can make use of the below function
function add(num){
add.sum || (add.sum = 0) // make sure add.sum exists if not assign it to 0
add.sum += num; // increment it
return add.toString = add.valueOf = function(){
var rtn = add.sum; // we save the value
return add.sum = 0, rtn // return it before we reset add.sum to 0
}, add; // return the function
}
Since functions are objects, we can add properties to it, which we are resetting when it's been accessed.
we can also use this easy way.
function sum(a) {
return function(b){
if(b) return sum(a+b);
return a;
}
}
console.log(sum(1)(2)(3)(4)(5)());
To make sum(1) callable as sum(1)(2), it must return a function.
The function can be either called or converted to a number with valueOf.
function sum(a) {
var sum = a;
function f(b) {
sum += b;
return f;
}
f.toString = function() { return sum }
return f
}
function sum(a){
let res = 0;
function getarrSum(arr){
return arr.reduce( (e, sum=0) => { sum += e ; return sum ;} )
}
function calculateSumPerArgument(arguments){
let res = 0;
if(arguments.length >0){
for ( let i = 0 ; i < arguments.length ; i++){
if(Array.isArray(arguments[i])){
res += getarrSum( arguments[i]);
}
else{
res += arguments[i];
}
}
}
return res;
}
res += calculateSumPerArgument(arguments);
return function f(b){
if(b == undefined){
return res;
}
else{
res += calculateSumPerArgument(arguments);
return f;
}
}
}
let add = (a) => {
let sum = a;
funct = function(b) {
sum += b;
return funct;
};
Object.defineProperty(funct, 'valueOf', {
value: function() {
return sum;
}
});
return funct;
};
console.log(+add(1)(2)(3))
After looking over some of the other solutions on here, I would like to provide my two solutions to this problem.
Currying two items using ES6:
const sum = x => y => (y !== undefined ) ? +x + +y : +x
sum(2)(2) // 4
Here we are specifying two parameters, if the second one doesnt exist we just return the first parameter.
For three or more items, it gets a bit trickier; here is my solution. For any additional parameters you can add them in as a third
const sum = x => (y=0) => (...z) => +x + +y + +z.reduce((prev,curr)=>prev+curr,0)
sum(2)()()//2
sum(2)(2)()//4
sum(2)(2)(2)//6
sum(2)(2)(2,2)//8
I hope this helped someone

Categories

Resources