Is it possible to compose the following function in Ramda?
(a, b) => R.pipe(func1(a), func2(a))(b)
The aim is passing argument a to all functions in the pipe.
My initial thought was the following:
R.pipe(R.juxt([func1, func2]), R.apply(R.pipe))
But this gives TypeError: Cannot read property 'length' of undefined.
This is easier to express using S.pipe as it takes an array of functions to compose.
One option is to use R.ap:
> S.pipe(R.ap([S.add, S.mult, S.add], [3]), 10)
42
Another option is to use R.map with S.T, the thrush combinator:
> S.pipe(R.map(S.T(3), [S.add, S.mult, S.add]), 10)
42
You could then wrap one of these in a lambda to create a binary function:
const f = (a, b) => S.pipe(R.ap([S.add, S.mult, S.add], [a]), b);
f(3, 10); // add(3)(mult(3)(add(3)(10)))
// => 42
You have to create a curried version of all the functions, then call the curried version of each with a and finally use b in either R.pipe or R.reduce
Let's say that the functions that need to have a as the first argument are f,g,h (in that specific order) then we want to achieve the following expression
h(a, g(a, f(a, b)))
First of all let's create a curried function which receives two arguments, a single value v and a function fn, when this function receives all its required arguments it will simply return fn(v)
const rev = R.curry((v, fn) => fn(v))
Next we can create the curried versions of the functions with R.map and R.curry
// note the reversed order of the functions
// I'll use R.compose instead of R.pipe
let curriedVersion = R.map(R.curry, [h,g,f])
However we also need to use a as the first argument of the curried functions, we could call each curried function with a using R.map but instead we will use our special function rev
const curriedVersion = R.map(R.compose(rev(a), R.curry), [h,g,f])
Finally let's use this array of curried functions with R.compose and b
const result = R.compose.apply(undefined, curriedVersion)(b)
One liner (for the functions f,g,h in that specific order):
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [h,g,f]))(b)
const add = (a, b) => a + b
const sub = (a, b) => a - b
const mul = (a, b) => a * b
const rev = R.curry((v, fn) => fn(v))
const solver = (a, b) => R.compose.apply(undefined, R.map(R.compose(rev(a), R.curry), [mul,sub,add]))(b)
// mul(2, sub(2, add(2, 3)))
// mul(2, sub(2, 5))
// mul(2, -3)
// -6
console.log(solver(2, 3))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.21.0/ramda.min.js"></script>
Related
Can somebody explain to me how Array.reduce can put functions as arguments in function composition like this:
const composeB = (f, g) => x => f(g(x))
const add = a => b => a + b
const add5 = add(5)
const double = a => a * 2
const add5ThenDouble = [double, add5].reduce(composeB)
console.log(add5ThenDouble(6)); // 22
So, according to my knowledge (which is not enough) of reduce function is that Array.reduce iterate through an array like this - it takes each of array values and puts them through callback function with another argument (lets call it accumulator). The next array value will undergo the same callback function, but with (eventually) changed accumulator value.
What confuses me in code example above is:
1) Array is list of functions [double, add5].
2) In first iteration, composeB will receive arguments: f=accumulator (empty value), g=double(function). ComposeB should return emptyvalue(double(6)) (or maybe not??)
I know that I am missing something, but can someone explain me what?
The documentation for reduce says that the first argument is
A function to execute on each element in the array (except for the first, if no initialValue is supplied).
So in this case, you have not supplied an initialValue and so compose is only called once (with arguments double and add5).
var inc = (x) => ++x, // increment +1
x2 = (x) => x*2, // multiply by 2
sq = (x) => x*x; // square
var compose = (f,g) => (_) => g(f(_));
var f1 = [ sq, inc, inc ].reduce(compose, (_) => _);
f1(10); // 102
var f2 = [ inc, sq, inc ].reduce(compose, (_) => _);
f2(10); // 122
See the code above, notice:
identity function (_) => _ as default value (second argument) for reduce
compose will NOT return a number, it will return a FUNCTION that is a composition of all the functions that were passed in before... So - only when you CALL the (say) f1, only then the functions will be executed.
we are putting all the functions from list [a,b,c,d,e] into a chain of e,d,c,b,a (reverse order!) and then execute as e(d(c(b(a(10))))) getting the order we actually wanted.
(f,g) => (_) => g(f(_)) <-- function arguments are actually reversed when calling them. Longer version: function compose (f, g) { return function (z) { return g(f(z)); }; }
p.s.: i use var because i can ;)
I want to write a function that performs arithmetic on ALL the arguments supplied. So for instance, if I do:
calculate('+', 3, 5, 6)
It should return 14 (which is 3+5+6)
Or if I do
calculate('*', 6,3,6,8,)
It should return 864 (which is the equivalent of multiplying all those numbers).
The function should essentially be able to handle any amount of numbers I supply to it, while also being able to handle the main arithmetic operators such as + - / *
I'm new at programming. I've tried:
function mCalc(_operator){
if(_operator=='+'){
return arguments + arguments;
}
}
console.log(mCalc('+',5,5));
this is not working so i can't even move forward.
In each function you have an arguments object see the section Rest, default, and destructured parameters as it states:
The arguments object can be used in conjunction with rest, default, and destructured parameters.
function foo(...args) { return args; }
Once you have all the arguments which are needed for your calculation just use Array.prototype.reduce(). As the documentation which states:
The reduce() method executes a reducer function (that you provide) on each element of the array, resulting in a single output value.
I guess you can use as the following:
const mCalc = (_operator, ...args) => {
if(_operator === '+') {
return args.reduce((a, c) => a + c, 0);
}
// rest what you want to implement
}
const result = mCalc('+', 3, 5, 6, 2);
console.log(result);
I hope that helps!
You could take an object for the operators and reduce the values by using a function which returns a function for two operands.
By calling the function the operator is taken and the values are taken to an array by using rest parameters ....
This approach uses arrow functions, like
calculate = (op, ...values) => values.reduce(take(op));
^^^^^^^^^ name of the function/variable
^^^^^^^^^^^^^^^ parameters
^^ arrow
^^^^^^^^^^^^^^^^^^^^^^^ return value
const
operators = {
'+': (a, b) => a + b,
'*': (a, b) => a * b
},
take = op => operators[op],
calculate = (op, ...values) => values.reduce(take(op));
console.log(calculate('+', 3, 5, 6)); // 14
console.log(calculate('*', 6, 3, 6, 8));
In a recent interview, I was asked to write a function that adds numbers and accepts parameters like this:
add(1)(2)(3) // result is 6
add(1,2)(3,4)(5) // result is 15
The number of parameters is not fixed, and the arguments can be either passed in sets or individually.
How can I implement this add function?
Given your examples, the number of parameters is fixed in some ways.
As #ASDFGerte pointed out, your examples seem to return the result after three invocations. In this case a simple implementation without introducing terms like variadic and currying could be
function add(...args1){
return function(...args2){
return function(...args3){
return args1.concat(args2).concat(args3).reduce((a,b)=>a+b)}}}
console.log(add(1)(2)(3))
console.log(add(1,2)(3,4)(5))
Every invocation accepts a variable number of parameters.
However it would be nice to generalize the construction of this nested functions structure and you can accomplish that with currying.
But if you want to allow an arbitrary number of invocations, when you should stop returning a new function and return the result? There is no way to know, and this is a simple, unaccurate and partial explanation to give you the idea of why they said you cannot accomplish what they asked you.
So the ultimate question is: is it possible that you misunderstood the question? Or maybe it was just a trick to test you
Edit
Another option would be to actually invoke the function when no arguments are passed in, change the call to add(1)(2)(3)()
Here an example recursive implementation
function sum (...args) {
let s = args.reduce((a,b)=>a+b)
return function (...x) {
return x.length == 0 ? s : sum(s, ...x)
};
}
console.log(sum(1,2)(2,3,4)(2)())
At every invocation computes the sum of current parameters and then return a new function that:
if is invoked without parameters just return the current sum
if other numbers are passed in, invokes recursively sum passing the actual sum and the new numbers
I'm a bit late to the party, but something like this would work (a bit hacky though in my opinion):
const add = (a, ...restA) => {
const fn = (b, ...restB) => {
return add([a, ...restA].reduce((x, y) => x + y) + [b, ...restB].reduce((x, y) => x + y))
};
fn.valueOf = () => {
return [a, ...restA].reduce((x, y) => x + y)
};
return fn;
}
This function returns a function with a value of the sum. The tests below are outputing the coerced values instead of the actual functions.
console.log(+add(1,2)(3,4)(5)); // 15
console.log(+add(1)) // 1
console.log(+add(1)(2)) // 3
console.log(+add(1)(2)(3)) // 6
console.log(+add(1)(2)(3)(4)) // 10
Since it's a currying function, it will always return another function so you can do something like this:
const addTwo = add(2);
console.log(+addTwo(5)); // 7
using reduce and spread it can be done as below
function calc(...args1){
return function (...args2){
return function (...args3){
let merge = [...args1, ...args2, ...args3]
return merge.reduce((x ,y)=> x + y) ;
}
}
}
let sum = calc(10)(1)(4);
console.log("sum",sum);
They probably wanted to know how comfortable you were with "javascript internals", such as how and when methods like Function#toString and Function#valueOf, Function#[Symbol.toPrimitive] are called under the hood.
const add = (...numbers) => {
const cadd = (...args) => add(...args, ...numbers);
cadd[Symbol.toPrimitive] = () => numbers.reduce((a, b) => a + b);
return cadd;
}
console.log(
`add(1,2)(3,4)(5) =>`, add(1,2)(3,4)(5),
); // result is 15
console.log(
`add(1,2) =>`, add(1,2),
); // result is 3
console.log(
`add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5) =>`, add(1,2)(5)(1,2)(5)(1,2)(5)(1,2)(5),
); // result is 32
Recently I read about function composition in a Javascript book, and then on a website I saw someone reference it as currying.
Are they the same concept?
#Omarjmh's answer is good but the compose example is overwhelmingly complex for a learner, in my opinion
Are they the same concept?
No.
First, currying is translating a function that takes multiple arguments into a sequence of functions, each accepting one argument.
// not curried
const add = (x,y) => x + y;
add(2,3); // => 5
// curried
const add = x => y => x + y;
add(2)(3); // => 5
Notice the distinct way in which a curried function is applied, one argument at a time.
Second, function composition is the combination of two functions into one, that when applied, returns the result of the chained functions.
const compose = f => g => x => f(g(x));
compose (x => x * 4) (x => x + 3) (2);
// (2 + 3) * 4
// => 20
The two concepts are closely related as they play well with one another. Generic function composition works with unary functions (functions that take one argument) and curried functions also only accept one argument (per application).
// curried add function
const add = x => y => y + x;
// curried multiplication function
const mult = x => y => y * x;
// create a composition
// notice we only apply 2 of comp's 3 parameters
// notice we only apply 1 of mult's 2 parameters
// notice we only apply 1 of add's 2 parameters
let add10ThenMultiplyBy3 = compose (mult(3)) (add(10));
// apply the composition to 4
add10ThenMultiplyBy3(4); //=> 42
// apply the composition to 5
add10ThenMultiplyBy3(5); //=> 45
Composition and currying are used to create functions. Composition and currying differ in the way they create new functions (by applying args vs chaining).
Compose:
Compose should return a function that is the composition of a list of functions of arbitrary length. Each function is called on the return value of the function that follows. You can think of compose as moving right to left through its arguments.
Example:
var compose = function(funcs) {
funcs = Array.prototype.slice.call(arguments, 0);
return function(arg) {
return funcs.reduceRight(function (a, b) {
a = a === null ? a = b(arg) : a = b(a);
return a;
}, null);
};
};
var sayHi = function(name){ return 'hi: ' + name;};
var makeLouder = function(statement) { return statement.toUpperCase() + '!';};
var hello = compose(sayHi, makeLouder);
l(hello('Johhny')); //=> 'hi: JOHNNY!'
Currying:
Currying is a way of constructing functions that allows partial application of a function’s arguments.
Example:
var addOne = add(1);
var addTwo = add(2);
var addOneToFive = addOne(5);
var addTwoToFive = addTwo(5);
l(addOneToFive); //6
l(addTwoToFive); //7
JSBin with the above examples:
https://jsbin.com/jibuje/edit?js,console
Is it possible to define my own infix function/operator in CoffeeScript (or in pure JavaScript)? e.g. I want to call
a foo b
or
a `foo` b
instead of
a.foo b
or, when foo is global function,
foo a, b
Is there any way to do this?
ES6 enables a very Haskell/Lambda calculus way of doing things.
Given a multiplication function:
const multiply = a => b => (a * b)
You can define a doubling function using partial application (you leave out one parameter):
const double = multiply (2)
And you can compose the double function with itself, creating a quadruple function:
const compose = (f, g) => x => f(g(x))
const quadruple = compose (double, double)
But indeed, what if you would prefer an infix notation? As Steve Ladavich noted, you do need to extend a prototype.
But I think it can be done a bit more elegant using array notation instead of dot notation.
Lets use the official symbol for function composition "∘":
Function.prototype['∘'] = function(f){
return x => this(f(x))
}
const multiply = a => b => (a * b)
const double = multiply (2)
const doublethreetimes = (double) ['∘'] (double) ['∘'] (double)
console.log(doublethreetimes(3));
Actually adding this as an answer: no, this is not possible.
It's not possible in vanilla JS.
It's not possible in CoffeeScript.
You can with sweet.js. See:
http://sweetjs.org/doc/main/sweet.html#infix-macros
http://sweetjs.org/doc/main/sweet.html#custom-operators
Sweet.js extends Javascript with macros.
It acts like a preprocessor.
This is definitely not infix notation but it's kinda close : /
let plus = function(a,b){return a+b};
let a = 3;
let b = 5;
let c = a._(plus).b // 8
I don't think anyone would actually want to use this "notation" since it's pretty ugly, but I think there are probably some tweaks that can be made to make it look different or nicer (possibly using this answer here to "call a function" without parentheses).
Infix function
// Add to prototype so that it's always there for you
Object.prototype._ = function(binaryOperator){
// The first operand is captured in the this keyword
let operand1 = this;
// Use a proxy to capture the second operand with "get"
// Note that the first operand and the applied function
// are stored in the get function's closure, since operand2
// is just a string, for eval(operand2) to be in scope,
// the value for operand2 must be defined globally
return new Proxy({},{
get: function(obj, operand2){
return binaryOperator(operand1, eval(operand2))
}
})
}
Also note that the second operand is passed as a string and evaluated with eval to get its value. Because of this, I think the code will break anytime the value of operand (aka "b") is not defined globally.
Javascript doesn't include an infix notation for functions or sections for partial application. But it ships with higher order functions, which allow us to do almost everything:
// applicator for infix notation
const $ = (x, f, y) => f(x) (y);
// for left section
const $_ = (x, f) => f(x);
// for right section
const _$ = (f, y) => x => f(x) (y);
// non-commutative operator function
const sub = x => y => x - y;
// application
console.log(
$(2, sub, 3), // -1
$_(2, sub) (3), // -1
_$(sub, 3) (2) // -1
);
As you can see I prefer visual names $, $_ and _$ to textual ones in this case. This is the best you can get - at least with pure Javascript/ES2015.
You can get close by function currying:
const $ = (a) => (f) => f(a);
const plus = (a) => (b) => (a+b);
const twoPlusThree = $ (2) (plus) (3);
But I still haven't figured out a neat way to compose this construction.