menu

JavaScript

A community to get help with JavaScript, find jobs, outsource and much more!

Channels
Team

Javascript Combinators (Functional Programming)

March 12, 2019 at 2:41pm

Javascript Combinators (Functional Programming)

March 12, 2019 at 2:41pm

I wonder how composition will work if the inputs of a function is output of a two functions, for example

const compose = (...fns) => (data) => fns.reduceRight((value, acc) => acc(value) , data)
const map = fn => f => f.map(fn);
const add = a => b => a + b;
const toInt = a => parseInt(a);
const log = a => console.log(a);
const data = ["1", "2", "3"];
compose(
log,
map(number => add(toInt(number))(toInt(number))), // no this is bad, I know this is silly
)(data);

I know that the add(toInt(number))(toInt(number)) is silly (I just can't get a simpler example). But my question is, is there any other way to compose a function that its inputs is a result of two other functions? those two functions can be totally different of each other, on the example, those two functions are the same toInt(number). maybe there is a combinator for this type of composition?

Thanks in advanced!


March 13, 2019 at 3:26am

Hi am not sure if I got your question correctly. But in ramda if I need to apply different function to an input I compose it using juxt.

Edited
  • reply
  • like

I can't upload an image..

import { compose, juxt, multiply, add, sum } from 'ramda'
const applyFunctions = juxt([multiply(2), add(2)])
const result = compose(sum, applyFunctions)
// 2 * 2
// 2 + 2
// == 8
result(2)
Edited
like-fill
2
  • reply
  • like

Hi @joshuacalpuerto looks like that is what I want, Thanks for the answer thumbs up, hmm is there a list of rules on building this kind of composition, I mean, do you know how ramda comes up with this type of function? and the name of this kind of function? like the identity and always they are classified as combinators if I am not mistaken? So for juxt it is classified as?

  • reply
  • like

I haven't try the juxt function, but looks like the snippet is convincing

  • reply
  • like

Im no expert of functional programming but looking at this table, it seems juxt is an apply combinator. It is also derived from converge that you might want to look up as well.

Edited
like-fill
1
  • reply
  • like

Thanks @joshuacalpuerto, I will take a look on those.

  • reply
  • like

March 15, 2019 at 10:04am

I've tried juxt just now and based on the definition of ramda it applies a list of functions to a list of values, and always yield an array.

On the case above add(n: number)(n: number) doesn't accept an array, I assume that the R.sum of ramda accepts an array and the function will just run fine.

But lets say (just exploring more example) we will create an element with text inside:

// impure, but just an example, appends a node on an element (data always comes last, which is the element)
const appendChild = node => element => {
element.appendChild(node);
return element;
};
// just another util,
const createTextNode = data => document.createTextNode(data);
const createElement = element => document.createElement(element);
const compose = (...fns) => (data) => fns.reduceRight((value, acc) => acc(value) , data)
const labelText = createTextNode("label");
const divElement = createElement("div");
const divWithLabelText = appendChild(labelText)(divElement);
console.log(divWithLabelText)
// so appendChild is just like the add function on the above, it's curried
// and so using juxt below won't work
// const applyFunctions = juxt(...) // [resultOfCreateTextNode, resultOfCreateElement]
// const res = compose(appendChild, applyFunctions)

The question is, is there any other way to compose a function that its inputs is a result of two other functions? In this case the two other functions are createTextNode and createElement and their result is needed by appendChild respectively. Maybe there is a function that accepts an array and spread the items into the arguments of a curried function?

Edited
  • reply
  • like

BTW, the example above is to create an element with a text inside

  • reply
  • like

March 16, 2019 at 3:38am

Hey the issue is that the final function is not accepting an array, instead it is a curried function that accept 1 arity.

Why not reduce the function? similar to to my screenshot.

Sorry don't have that time to look at the snippet you post. If this won't solve the issue I will take a look closer to it.

Cheers!

Edited
  • reply
  • like
  • reply
  • like

March 16, 2019 at 10:32am

@joshuacalpuerto yes I know that the issue is the final function is not accepting an array but curried with an arity.

  • reply
  • like

Continuing on, looks like reduce does the job. I haven't thought of that, reduce was used to partially applied a function using an array until it resolves, Thanks @joshuacalpuerto cheers

  • reply
  • like

@joshuacalpuerto yes I know that the issue is the final function is not accepting an array but curried with an arity.

Hey sorry I know you know. I Just forgot to add '?' on that phrase. I'm clarifying the issue.

  • reply
  • like

Continuing on, looks like reduce does the job. I haven't thought of that, reduce was used to partially applied a function using an array until it resolves, Thanks @joshuacalpuerto cheers

Perfect! You're welcome!

like-fill
1
  • reply
  • like

April 15, 2019 at 12:45pm

@cmandocdoc This was a really good question. It's something I've found myself having to sort out a lot, but never thought to crystallise the solution in writing. Your question inspired me to write it up so I don't forget again in future. Unfortunately it got a bit long to post here, so I stuck it on my blog.

like-fill
2
  • reply
  • like

May 13, 2019 at 6:11am

@jrsinclair, I've read your blog just now and it really helps me, especially for this kind a of problem, thank you. hmm can I figure out how you know about the blackbird combinator? I always thought, that, maybe there is a list of standard combinators to handle different cases of input?

Edited
  • reply
  • like

@jrsinclair, I've read your blog just now and it really helps me, especially for this kind a of problem, thank you. hmm can I figure out how you know about the blackbird combinator? I always thought, that, maybe there is a list of standard combinators to handle different cases of input?

@cmandocdoc The only JS-specific list that I've ever been able to find is this one: https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45 You'll notice that the blackbird combinator isn't in the main body. I had to read all the comments to find it. Someone else was asking about the same thing. There are whole books written on combinators though. They're just usually not written for front-end developers. If you want to find out more, one of the best resources is this talk by Reginald Braithwaite:

like-fill
1
  • reply
  • like

@cmandocdoc The only JS-specific list that I've ever been able to find is this one: https://gist.github.com/Avaq/1f0636ec5c8d6aed2e45 You'll notice that the blackbird combinator isn't in the main body. I had to read all the comments to find it. Someone else was asking about the same thing. There are whole books written on combinators though. They're just usually not written for front-end developers. If you want to find out more, one of the best resources is this talk by Reginald Braithwaite:

Thank you very much @jrsinclair, I will share your blog and this comment to my colleagues it is very helpful. :thumbsup: :thumbsup:

  • reply
  • like