Function composition using Ramda - javascript

I have a 2 functions and 1 variable which when combined take the form
const value = f(g(x))(x)
That is, f(g(x)) returns a function taking x again. I don't like this redundancy and it's preventing me from declaring my function pointfree.
What Ramda function do I need to transform this into R.something(f, g)(x)?
Here's a working example, testable in http://ramdajs.com/repl/?v=0.24.1,
const triple = x => x * 3
const conc = x => y => x + " & " + y
const x = 10
conc(triple(x))(x)
// I'm looking for R.something(conc, triple)(x)

You can use R.chain
const something = chain(conc, triple)
You can see this in action on the Ramda repl.

you can make a function result which does
const triple = x => x * 3
const conc = x => y => x + " & " + y
let result = (a, b) => e => a(b(e))(e)
const x = 10
console.log(conc(triple(x))(x));
// I'm looking for R.something(conc, triple)(x)
console.log(result(conc, triple)(x));

Related

How to encode a Deferred type with Church?

With functions we can abstract from any type. Here is the Option type as an example:
const Some = x => y =>
k => k(x);
const None = y =>
k => y;
const sqr = n => n * n;
const run = f => t => t(f);
const x = Some(5) (0),
y = None(0);
run(sqr) (x); // 25
run(sqr) (y); // 0
Now I want to encode a deferred type to obtain a lazy effect in Javascript. But I don't know the right approach and if such an endeavor even makes sense with Church Encoding. Here is my first shot:
const Deferred = thunk =>
k => k(thunk());
const inc = n => n + 1;
const sqr = n => n * n;
const run = f => t => t(f);
const x = Deferred(() => inc(4));
run(sqr) (x); // 25
I am totally in the dark here. Does this approach lead to anything meaningful?
Church encoding (and more precisely, Scott encoding) provide a way to encode branching in a data type with different cases (e.g. instance constructors). Your Deferred type however is a (newtype) wrapper over a function that takes a continuation, there are no multiple cases to be encoded. I don't think you can apply the concept here.

javascript expression seperated by ,

I stumbled upon this javascript statement:
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
I don't understand the expression f(y), x. With some experimenting I found out that this is working too: f(y(x)). It gives the exact same result (for my example at least and is much more understandable to me).
const pipe1 = (...fns) => x => fns.reduce((y, f) => f(y), x);
const pipe2 = (...fns) => x => fns.reduce((y, f) => f(y(x)));
const addThree = x => x + 3;
const addTwo = x => x + 2;
let x1 = pipe1(addTwo, addThree)(2); //x1 is seven
let x2 = pipe2(addTwo, addThree)(2); //x2 is seven
Then I thought that this is some syntax sugar for x,y for x(y) and tried this:
let z = n => addThree, n; //addThree(n)? no, that does not work!
I need some light on the expression f(y), x). Yes I read some stackoverflow articles that the expression is evaluated form left to right and the last is returned. It just makes no sense to me in this example.
fns.reduce((y, f) => f(y), x)
If you format it, it might make more sense.
fns.reduce(
(y, f) => f(y),
x
)
So (y, f) => f(y) is the first parameter to reduce (the reducer function), and x is the 2nd parameter to reduce, which is the initial value.
In conclusion, you were thrown off by the lack of grouping with the arrow function. :)
"Value-X" is going to be the x variable, passed as the 2nd parameter to the reduce function.
const pipe = (...fns) => x => fns.reduce((y, f) => f(y), x);
const foo = pipe(func1, func2, func3);
foo("Value-X");
The expression can be rewritten as this, if it helps to clarify things:
function pipe(...fns) {
return function (x) {
function chain(y, f) {
// y = previous return value
// If this is the first time the function is called, y = x
return f(y);
}
return fns.reduce(chain, x);
}
}

How to combine functions in another FP?

I am learning function programming in JavaScript, currently I have the following code.
I would like to combine this two functions in another function which alllow an user to pass a value in and having the result equal to the value passed plus 10 multiply 3 using the following functions.
Pseudo code example:
const myFormulat= add(10).multiply(3);
How can I write this function using only vanilla JS ES6?
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
// my calculation
// get x add 10 and after multiply by 3
Bear traps and landmines
This answer exists solely to demonstrate why this is not such a great idea ā€“ complexity is thru the roof with basically no gain. Note we must tell our function when to end, so i've added a special function call so our expressions will look like this
.add(3).mult(4).call(x)
// where x is the input for the entire function chain
One last change is our library of functions add, mult, et al must be wrapped in some scope that limits the reach of our proxy. This scope tells us exactly where the functions we wish to chain exist.
Oh and if the title of this section wasn't a warning enough, we use a Proxy too.
// helpers
const identity = x => x
const comp = f => g => x => f(g(x))
// magic wand
const using = scope => {
let acc = identity
let p = new Proxy({
call: x => acc(x),
}, {
get: (target, name) => {
if (name in target)
return target[name]
else if (name in scope)
return x => {
acc = comp (scope[name](x)) (acc)
return p
}
else
throw Error(`${f} is not undefined in ${scope}`)
}
})
return p
}
// your functions wrapped in a scope
const math = {
add: x => y => x + y,
mult: x => y => x * y
}
// chain it up
const main = using(math).add(3).mult(4).add(5).mult(6).call
console.log(main(2))
// (((2 + 3) * 4) + 5) * 6
// ((5 * 4) + 5) * 6
// (20 + 5) * 6
// 25 * 6
// 150
Function composition
But seriously, don't do that. Pushing everything through the . operator is unnatural given your starting point and you should be looking for more effective means to combine functions.
We can effectively do the same thing using a slightly different notation ā€“ the biggest difference here is complexity is almost zero
const compose = (f,...fs) => x =>
f === undefined ? x : compose (...fs) (f(x))
const add = x => y => x + y
const mult = x => y => x * y
const main = compose (add(3), mult(4), add(5), mult(6))
console.log(main(2)) // => 150
Functors
Maybe you don't like traditional function composition, and that's fine, because we have yet another way to tackle this problem using Functors ā€“ simply put, a Functor is a container with a map function.
Below we have a Box function which puts values in our container. The map function accepts a function and creates a new Box with the return value of the user-specified function. Lastly, we have a fold function which allows us to take our value out of the box
Again, it changes up the way we write the code a little bit, but the reduction is complexity is tremendous (compared to the Proxy example)
const Box = x => ({
map: f => Box(f(x)),
fold: f => f(x)
})
const add = x => y => x + y
const mult = x => y => x * y
const main = Box(2).map(add(3)).map(mult(4)).map(add(5)).map(mult(6)).fold
main(console.log) // 150
See: http://scott.sauyet.com/Javascript/Talk/Compose/2013-05-22/
function add(x){
return function(y){
return y + x;
};
}
function multiply(x){
return function(y){
return y * x;
};
}
Function.prototype.compose = function(g) {
var fn = this;
return function() {
return fn.call(this, g.apply(this, arguments));
};
};
var f = multiply(3).compose(add(10));
console.log(f(5));
If i understand you correctly you are trying to figure out function chaining in JavaScript
Function Chaining or Method chaining is a common pattern in JS world.
one of the methods in which you can achieve chaining is by creating a class and returning this operator or current object reference back
You can find interesting tutorial regarding this in following URL
https://www.bennadel.com/blog/2798-using-method-chaining-with-the-revealing-module-pattern-in-javascript.htm

Why all subscribers are not called in RxJS

This is my code
let x = Rx.Observable.create(obs => window.obs = obs);
y = x.map(x=>x+2);
x.subscribe(v=>console.log("x got ",v));
y.subscribe(v=>console.log("y got ",v));
obs.next(1);
Output is
y got 3
I was expecting output to be
x got 1
y got 3
What am I missing here? Thanks
You are overwriting the window.obs upon the second subscription.
If your usecase requires you to procedurally invoke emissions then you can use a Subject instead of creating an observable yourself:
const subj = new Rx.Subject();
const sub1 = subj.subscribe(x => console.log('x got: ' + x));
const sub2 = subj.map(v => v * 2).subscribe(y => console.log('y got: ' + y));
subj.next(2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.1.0/Rx.js"></script>

To "combine" functions in javascript in a functional way?

I'm learning functional programming and I wonder if there is a way to "combine" functions like this:
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
combine(1); //1
combine(triple)(triple)(plusOne)(1); // 10
combine(plusOne)(triple)(isZero)(-1); // true
If the para is a function, it "combines" the function into itself, and if not it will return the final result.
Thanks!
heritage
This is a concept from maths called function composition.
f(x) = y
g(y) = z
g(f(x)) = z
(gā€¢f)(x) = z
That last line is read "g of f of x equals z". What's great about composed functions is the elimination of points. Notice in g(f(x)) = z we take an x input and get a z output. This skips the intermediate point, y.
Composition is a great way to create higher-order functions and keep your code sparkly clean. It's plain to see why we'd want this in our Javascript programs.
comp
JavaScript is a multi-paradigm language with rich support for functions. We can create a simple comp function, which combines two input functions, g and f, and results in a new function -
function triple(x) {
return x * 3
}
function plusOne(x) {
return x + 1
}
function comp(g, f) {
return function(x) {
return g(f(x)) // "g of f of x"
}
}
const myfunc =
comp(triple, plusOne)
console.log(myfunc(1))
Evaluation
triple(plusOne(1))
triple(2)
6
compose
Just as the question suggests, it's likely we will want to combine more than two functions. Below we write compose which takes all of the input functions and reduces them using our simple comp from above. If no functions are given, we return the empty function, identity -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const comp = (g, f) =>
x => g(f(x)) // "g of f of x"
const identity = (x) =>
x
const compose = (...all) =>
all.reduce(comp, identity)
const myfunc =
compose(triple, triple, plusOne) // any amount of funcs
console.log(myfunc(1))
Evaluation
triple(triple(plusOne(1)))
triple(triple(2))
triple(6)
18
pipe
You can be as creative as you like. Below, we write pipe which allows our programs to read in a comfortable left-to-right direction -
const triple = (x) =>
x * 3
const plusOne = (x) =>
x + 1
const pipe = x =>
f => pipe(f(x))
pipe(1)(plusOne)(triple)(triple)(console.log) // 18
pipe(3)(triple)(plusOne)(triple)(plusOne)(console.log) // 31
Evaluation of expression one -
f => pipe(f(1))
pipe(plusOne(1))
f => pipe(f(2))
pipe(triple(2))
f => pipe(f(6))
pipe(triple(6))
f => pipe(f(18))
pipe(console.log(18))
18
and expression two -
f => pipe(f(3))
pipe(triple(3))
f => pipe(f(9))
pipe(plusOne(9))
f => pipe(f(10))
pipe(triple(10))
f => pipe(f(30))
pipe(plusOne(31))
f => pipe(f(31))
pipe(console.log(31))
31
related techniques
Curried functions and partial application are concepts that gel with function composition. pipe above is introduced in another Q&A as $ and demonstrated again here -
const $ = x => // "pipe", or whatever name you pick
k => $ (k (x))
const add = x => y => // curried add
x + y
const mult = x => y => // curried mult
x * y
$ (1) // 1
(add (2)) // + 2 = 3
(mult (6)) // * 6 = 18
(console.log) // 18
$ (7) // 7
(add (1)) // + 1 = 8
(mult (8)) // * 8 = 64
(mult (2)) // * 2 = 128
(mult (2)) // * 2 = 256
(console.log) // 256
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
var combine = function (v) {
var fn = [];
function _f(v) {
if (typeof v === 'function') {
fn.push(v);
return _f;
} else {
return fn.reduce(function (x, f) { return f(x); }, v);
}
}
return _f(v);
};
var a, b;
console.log(combine(1)); //1
console.log(combine(triple)(triple)(plusOne)(1)); // 10
console.log(combine(plusOne)(triple)(isZero)(-1)); // true
console.log(a = combine(plusOne)); // function ...
console.log(b = a(triple)); // function ...
console.log(b(5)); // 18
console.log(combine(triple)(plusOne)(triple)(plusOne)(triple)(plusOne)(1)); // 40
// #naomik's examples
var f = combine(triple);
var g = combine(triple)(triple);
console.log(f(1)); // 3
console.log(g(1)); // 9 (not 6 as you stated)
Function composition has already been detailed in other answers, mostly https://stackoverflow.com/a/30198265/4099454, so my 2 cents are straight onto answering your latest question:
If the para is a function, it "combines" the function into itself, and if not it will return the final result. Thanks!
const chain = (g, f = x => x) =>
typeof g === 'function'
? (y) => chain(y, (x) => g(f(x)))
: f(g);
// ====
const triple = x => x * 3;
const inc = x => x + 1;
const isZero = x => x === 0;
console.log(
chain(inc)(triple)(isZero)(-1),
);
It is also possible to build a complex Functionality by Composing Simple Functions in JavaScript.In a sense, the composition is the nesting of functions, passing the result of one in as the input into the next. But rather than creating an indecipherable amount of nesting, we'll create a higher-order function, compose(), that takes all of the functions we want to combine, and returns us a new function to use in our app.
function triple(x) {
return x * 3;
}
function plusOne(x) {
return x + 1;
}
function isZero(x) {
return x === 0;
}
const compose = (...fns) => x =>
fns.reduce((acc, cur) => {
return cur(acc);
}, x);
const withCompose = compose(triple, triple, isZero);
console.log(withCompose(1));
You can simply call the function on the return values themselves, for example:
plusOne(triple(triple(1))) // 10
isZero(triple(plusOne(-1))) // true

Categories