Live data from Hacker News

Folding Promises in JavaScript

codementor.io

21–30 of 48 posts

Re: Folding Promises in JavaScript

#23
post #19

Earlier quoted context omitted.

I feel nothing has improved code readability like the recent mainstreaming of map/filter/fold/reduce and "const all the things". This type of code is so easy to follow, reason about and trivial to debug at every step, once you internalize the few primitive functions. I don't think you need to necessarily memorize these transformation names, but writing these types of functions is all I seem to be doing these days, tr…

I feel the code I wrote while on this bandwagon is the hardest to understand for others and for me myself today. pullAllBy(pluck(things, 'bar').map(compose(xor, lol, rofl)).reduce(differenceWith('id')) Just write your transformations inline and go work on the next feature.

The trick is to break that (on the dots) into three const assignments with descriptive names. Practically self-documenting, easily debuggable.

If you don't use the builtin transformations, you'll just end up re-implementing them, poorly. And adding to the cognitive overhead with new concepts. And I have to read your code with a fine-toothed comb to ensure it's really side-effect free. I don't advocate turning everything into a named function as in your example though, short one-off functions should all be inline IMO.

Re: Folding Promises in JavaScript

#24
post #19

Earlier quoted context omitted.

I feel nothing has improved code readability like the recent mainstreaming of map/filter/fold/reduce and "const all the things". This type of code is so easy to follow, reason about and trivial to debug at every step, once you internalize the few primitive functions. I don't think you need to necessarily memorize these transformation names, but writing these types of functions is all I seem to be doing these days, tr…

I feel the code I wrote while on this bandwagon is the hardest to understand for others and for me myself today. pullAllBy(pluck(things, 'bar').map(compose(xor, lol, rofl)).reduce(differenceWith('id')) Just write your transformations inline and go work on the next feature.

the nice thing is that you can easily split that line up as much as makes sense, should you decide you need to access some intermediate form of the data. and you can use the variable names as a comment that explains what that chunk of transformations represents.

so someone reading over it can kind of skim down the left side and follow what's happening and scan to the right if they need to understand some part in detail

Re: Folding Promises in JavaScript

#25
post #2

I don't know much about these concepts but isn't `const objToArray = ({ a }) => [a]; ` losing data, that being the key of the value in the object? I'm asking because it says that "Isomorphism is a pair of transformations between two categories with no data loss". In any case, this is very helpful, thanks for writing/sharing.

Yeah, that was my though as well. It seems like what you need is something like:

   const objToArray = Object.entries
   const arrayToObj = (a) => a.reduce((a, [k, v]) => ((a[k]=v), a), {})
   arrayToObj(objToArray({ foo: 'bar' })) // { foo: 'bar' }

Re: Folding Promises in JavaScript

#26
post #19

Earlier quoted context omitted.

I feel nothing has improved code readability like the recent mainstreaming of map/filter/fold/reduce and "const all the things". This type of code is so easy to follow, reason about and trivial to debug at every step, once you internalize the few primitive functions. I don't think you need to necessarily memorize these transformation names, but writing these types of functions is all I seem to be doing these days, tr…

I feel the code I wrote while on this bandwagon is the hardest to understand for others and for me myself today. pullAllBy(pluck(things, 'bar').map(compose(xor, lol, rofl)).reduce(differenceWith('id')) Just write your transformations inline and go work on the next feature.

If only you could still recognize it as a transformation when it is inline

Re: Folding Promises in JavaScript

#27
post #3

> Folding Promises in JavaScript Or: How to make simple things complex and make a codebase a complete puzzle for those that come after you?

These things map/reduce/compose/flatmap are universal - they're in java, python, c#, Ocaml, Haskell, lisp, ruby, javascript...

Complaining about learning them is like complaining about for loops. They just exist.

Just because some are more familiar with for loops than map doesn't mean that more universal, immutable, expression - based solutions are not widely familiar and easy to understand to programmers coming from other languages.

Readability is subjective.

Re: Folding Promises in JavaScript

#28
post #8

>How can we make it better ? Let's start by removing the requirement for identity value to always be the promise. I challenge the view that making the identity value being able to be something other than a Promise is 'making it better'. Pointless abstraction is one of my pet peeves in this industry. This looks like it has gone from a fairly straightforward, if kludgy, piece of code to something far more complex. Why…

Same reason given in the bluebird library documentation: > Promise.reduce will start calling the reducer as soon as possible, this is why you might want to use it over Promise.all (which awaits for the entire array before you can call Array#reduce on it). Whether this is ever necessary is another matter :)

    let accumulator = 0
    for (let item of array) {
      const value = await item
      // your code here
    }
Is identical, doesn't use 'cool' reduce features but is much easier to read in my opinion.

Re: Folding Promises in JavaScript

#29
post #20

Earlier quoted context omitted.

Same reason given in the bluebird library documentation: > Promise.reduce will start calling the reducer as soon as possible, this is why you might want to use it over Promise.all (which awaits for the entire array before you can call Array#reduce on it). Whether this is ever necessary is another matter :)

I suppose this might be useful in situations where you are querying an API(s) with multiple requests and some will certainly return seconds before others. This way you could have the same reducer handle the results and begin updating the UI as the results come in. An example real-world app might be a price comparison tool or social media aggregator.

> I suppose this might be useful in situations where you are querying an API(s) with multiple requests and some will certainly return seconds before others.

But it's still a serialized operation so the parallelism is still limited. What's really needed is a "parallel reduce" using something like C's select function that will reduce in an arbitrary order using any promises that are ready at any given step.

Re: Folding Promises in JavaScript

#30
post #8

>How can we make it better ? Let's start by removing the requirement for identity value to always be the promise. I challenge the view that making the identity value being able to be something other than a Promise is 'making it better'. Pointless abstraction is one of my pet peeves in this industry. This looks like it has gone from a fairly straightforward, if kludgy, piece of code to something far more complex. Why…

> Pointless abstraction is one of my pet peeves in this industry. This looks like it has gone from a fairly straightforward, if kludgy, piece of code to something far more complex. Why not just: [code]

Your example code works just fine for promises of course, but not all monads support a coalescing operation like Promise.all.

So even though this article only discusses folding over Promises, the core idea here can be generalised to any monad type (such as Promise, Result, Option, or anything else)

Post reply on HN