Javascript Combinators (Functional Programming)
March 12, 2019 at 2:41pmJavascript Combinators (Functional Programming)
March 12, 2019 at 2:41pmI 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.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// == 8result(2)
Hi 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?I haven't try the
juxt
function, but looks like the snippet is convincingThanks , I will take a look on those.
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?BTW, the example above is to create an element with a text inside
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!
March 16, 2019 at 10:32am
yes I know that the issue is the final function is not accepting an array but curried with an arity.
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 cheers
Perfect! You're welcome!
April 15, 2019 at 12:45pm
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.
May 13, 2019 at 6:11am
, 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?
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 , I will share your blog and this comment to my colleagues it is very helpful. :thumbsup: :thumbsup: