I have 5 functions: func1(), func2(), func3(), func4(), func5(). I need to implement the compositionFunc() function, which can take any number of functions as arguments, and create a composition from them. The compositionFunc() function takes my 5 functions as arguments. The compositionFunc() function returns a function that takes its initial value as an argument. This nested function successively passing through an array of functions with each iteration returns the result of calling the accumulated value of the current function-argument. The result of one function can be passed as an argument to another function. How can i do this?
const func1 = (arg1) => {
return arg1;
};
const func2 = (arg2) => {
return arg2;
};
const func3 = (arg3) => {
return arg3;
};
const func4 = (arg4) => {
return arg4;
};
const func5 = (arg5) => {
return arg5;
};
const compositionFunc = () => {
...
};
you can define a function like this
const pipe = (...functions) => args => functions.reduce((res, f) => f(res), args)
const combine = (...functions) => args => functions.reduceRight((res, f) => f(res), args)
const plus1 = x => x + 1
const double = x => x * 2
const pipeFunction = pipe(plus1, double)
const combineFunction = combine(plus1, double)
console.log(combineFunction(1)) // (1 * 2) + 1
console.log(pipeFunction(1)) // (1 + 1) * 2
A simple reduce can accomplish that:
function pipe(input, ...func) {
return func.reduce((a, f) => f(a), input);
}
You pass it an initial value + chain of functions.
Example:
function f1(val) {
return val + 1;
}
function f2(val) {
return val * 10;
}
console.log(pipe(2, f1, f2)); //=> 30
Related
I have an exercise to make a function executeFunctions which takes as arguments a list of async functions and an argument, e.g. number.
The functions have to happen one after another, so if fun1 ends, fun2 needs to start with the value which was returned from fun1.
The problem is that I can't use async and await. I wanted to do it using reduce, but I guess that it wants to execute const res1 and go further before it returns a value (because of setTimeout).
Is there any way to do it without async and await?
const fun1 = function(value) {
return setTimeout(() => value*2, 3000)
}
const fun2 = function(value) {
return setTimeout(() => value*4, 3000)
}
const cb2 = (value) => {
return value*10
}
const executeFunctions = (funTab, cb) => (n) => {
const res1= funTab[0](n)
console.log(res1)
const resReduce = funTab.reduce((prev,curr) => {
const res2 = curr(prev)
return prev+res2
}, res1)
return cb(resReduce)
};
executeFunctions([fun1,fun2], cb2)(2)
We can use Promise-chaining:
const fun1 = function(value) {
return Promise.resolve(value * 2);
}
const fun2 = function(value) {
return Promise.resolve(value * 2);
}
const fun3 = function(value) {
return Promise.resolve(value * 2);
}
const executeFunctions = (funcList) => (n) => {
let chain = Promise.resolve(n); // initial value
for (let i = 0; i < funcList.length; i++) {
chain = chain.then(funcList[i]); // keep chaining
}
return chain; // last promise
};
const main = () => {
// we need to wait for the last promise in order to print the result
executeFunctions([fun1, fun2, fun3])(2).then(x => console.log('solution is:', x));
}
main() // prints: "solution is: 16"
or, we can also use a modified version of the suggested reduce solution, by changing the implementation of executeFunctions as follows (the rest of the code should remain as in the previous snippet):
const executeFunctions = (funcList) => (n) => {
const init = Promise.resolve(n);
const res = funcList.reduce((p, c) => {
return p.then(c)
}, init);
return res;
};
I need to write a function in JavaScript that takes a number and returns an object that returns chainable functions (without using OOP).
Example:
func(3).not().not().equals(4)
would outputs false.
And:
func(5).equals(5)
would output: true
This is the code I have written:
const func = (obj) => {
const obj2 = {
not: () => {
return !obj
},
equals: (num) => {
return obj === num
}
}
return obj2
}
It works when I call func(3).not() or func(5).equals(5), but doesn't allow me to chain the functions so calling func(5).not().equals(5) returns an error saying that this is not a function.
What am I not seeing here?
That's a very weird way to compose functions. Let's think about what's actually happening.
func(3).not().not().equals(4)
// is equivalent to
not(not(equals(4)(3)))
// where
const not = x => !x;
const equals = x => y => x === y;
The simplest way to implement this chain would be as follows.
const equals = x => toBool(y => x === y);
const toBool = func => ({
not: () => toBool(x => !func(x)),
func
});
const example1 = equals(4).not().not().func(3);
const example2 = equals(5).func(5);
console.log(example1); // false
console.log(example2); // true
However, this is a forward chain. You want a backward chain. Unfortunately, there's a problem.
In a forward chain .func(x) marks the end of the chain.
In a backward chain .equals(x) marks the end of the chain.
This means that in a backward chain, you wouldn't be able to write the following expression.
func(3).not().not().equals(4).add(1)
// expected to be equivalent to
not(not(equals(4)(add(1)(3))))
// but actually equivalent to
not(not(equals(4)(3))).add(1)
// which evaluates to
false.add(1)
On the other hand, you would be able to do this quite easily using a forward chain.
const id = x => x;
const toNum = func => ({
add: x => toNum(y => x + func(y)),
equals: x => toBool(y => x === func(y)),
func
});
const toBool = func => ({
not: () => toBool(x => !func(x)),
func
});
const { add, equals } = toNum(id);
const example1 = equals(4).not().not().func(3);
const example2 = add(1).equals(4).not().not().func(3);
console.log(example1); // false
console.log(example2); // true
By the way, this is an object-oriented design pattern even though it doesn't make use of classes.
My advice would be to write plain old functions.
const add = (x, y) => x + y;
const equals = (x, y) => x === y;
const not = x => !x;
const example1 = not(not(equals(4, 3)));
const example2 = not(not(equals(4, add(1, 3))));
console.log(example1); // false
console.log(example2); // true
The simplest solutions are usually the best. Source: Occam's razor.
To return another object with the same methods that wraps the new value, simply call func again:
const func = (obj) => {
const obj2 = {
not: () => {
return func(!obj)
// ^^^^^^^^^^^^^^^^^
},
equals: (num) => {
return obj === num
}
}
return obj2
}
console.log(func(3).not().not().equals(4))
console.log(func(5).equals(5))
console.log(func(3).not())
You can use a closure to store both the initial input and the state of the operation:
const func = (input) => {
let not = false
const obj = {
not: () => {
not = !not
return obj
},
equals: (num) => {
return not ? input !== num : input === num
}
}
return obj;
}
console.log(func(5).not().equals(5))
console.log(func(5).not().not().equals(5))
console.log(func(5).not().equals(4))
console.log(func(5).not().not().equals(4))
You could take an object for return as interface and store value and negation.
var object = {
func: function (value) {
object.left = value;
return object;
},
not: function() {
object.negation = !object.negation;
return object;
},
equals: function (value) {
var result = value === object.value;
return object.negation ? !result : result;
}
},
func = object.func;
console.log(func(3).not().not().equals(4));
I was looking into pipe functions and I came across this reduce function which takes the _pipe function as the parameter. The _pipe function has two params a,b and then returns another function.
How does reduce work here?
add3 = x => x + 3;
add5 = x => x + 5;
const _pipe = (a, b) => (arg) => b(a(arg))
const pipe = (...ops) => ops.reduce(_pipe)
const add = pipe(add3, add5)
add(10)
output
18
look at pipe function definition:
const pipe = (...ops) => ops.reduce(_pipe)
It receives array of functions called ops (this is called rest params).
Then we call reduce for ops array. Reducer function has 2 params: accumulator and current value.
Here is our _pipe written with human readable variables:
const _pipe = (accumulator, currentValue) => (arg) => currentValue(accumulator(arg));
So the result of _pipe will be curried functions from ops array.
If it's [add3, add5] then result will be (arg) => add3(add5(arg))
If it's [add3, add5, add2] then result is: (arg) => add2(accumulator(arg)) where accumulator is (arg) => add3(add5(arg)).
You simply compose all functions from array using reduce. Then pass initial value which is 10.
It's like: add3(add5(10)) = 18
the reduce function is equivalent to
add3 = x => x + 3;
add5 = x => x + 5;
const _pipe = (a, b) => (arg) => b(a(arg))
const pipe = (...ops) => {
// create a base function
let sum = x => x;
// for every operation
for (let op of ops) {
// call _pipe with sum and it
// equivalent to sum = x => sum(op(x))
sum = _pipe(sum, op)
}
// return the resulting function
return x => sum(x)
}
const add = pipe(add3, add5)
console.log(add(10))
I have an object foo that I want to call as a function foo(...). I can do that like this:
foo = n => n * foo.factor;
foo.factor = 2;
foo(2) // returns 4
But for this to work I need to write the function (n => n * foo.factor) before other properties. How can I write it after? I want to do something like this:
foo = { factor: 2 }
// write function
foo(2) // returns 4
Maybe use a small utility:
const functionize = (obj, fn) => Object.assign(fn, obj);
So one can do:
let foo = { factor: 2 };
foo = functionize(foo, n => n * foo.factor);
foo(2);
Or you just use a regular function:
foo.factor = 2;
function foo(n) { return foo.factor * n; }
I wish there was a way to define my object as a function and then later change its body...
const foo = (...args) => (foo.body || () => null)(...args);
foo.factor = 2;
foo.body = n => foo.factor * n;
foo(2);
You could do it with a simple helper:
const annotate = (f, annotations) => {
Object.assign(f, annotations);
return f;
};
...which you'd use like this:
foo = annotate(n => n * foo.factor, {factor: 2});
foo(2); // returns 4
But I wouldn't. Instead, I'd create a function builder:
const makeFoo = factor => n => n * factor;
and then:
const foo = makeFoo(2);
foo(2); // returns 4
Live example:
const makeFoo = factor => n => n * factor;
const foo2 = makeFoo(2);
console.log(foo2(2)); // returns 4
const foo4 = makeFoo(4);
console.log(foo4(2)); // returns 8
When using bind in JS, one can create functions with predefined arguments, e. g.:
var add = function (a, b) {
return a + b;
};
var addToThree = add.bind(null, 3);
But how to I do this if I want to predefine the second, third etc. argument, but not the first?
In ES2015 you can do something like this:
const partial = fn => (...pargs) => (...args) => fn.apply(null, [...pargs, ...args]);
const partialRight = fn => (...pargs) => (...args) => fn.apply(null, [...args, ...pargs.reverse()]);
const myFunc = (one, two, three, four) => {
console.log(one);
console.log(two);
console.log(three);
console.log(four);
};
const myFuncPartial = partial(myFunc)('1');
const myFuncPartialRight = partialRight(myFuncPartial)('4', '3');
myFuncPartialRight('2');
You can do
var add = function (a, b) {
b = b || 5;
return a + b;
};
In ES6 Default Parameters can be used in a very easy way
var add = function (a, b=5) {
return a + b;
};
and call it like add(3);