Live data from Hacker News

Folding Promises in JavaScript

codementor.io

31–40 of 48 posts

Re: Folding Promises in JavaScript

#31
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 :)

The example isn't using Promise.reduce.

Re: Folding Promises in JavaScript

#32

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 :)

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.

Wouldn’t this code only execute 1 promise at a time? I thought Promise.all allowed promises to be resolved in parallel

Re: Folding Promises in JavaScript

#33

Earlier quoted context omitted.

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.

Wouldn’t this code only execute 1 promise at a time? I thought Promise.all allowed promises to be resolved in parallel

Sorry, in the sense of being identical to the original code in the linked post (reduce), not the comment.

Re: Folding Promises in JavaScript

#34

Earlier quoted context omitted.

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.

Wouldn’t this code only execute 1 promise at a time? I thought Promise.all allowed promises to be resolved in parallel

Indeed. You most likely should do `await Promise.all` and then do the reduction.

Re: Folding Promises in JavaScript

#35

I can't quite understand the difference between endomorphism ("input and output of the transformer must be from the same category") and homomorphism ("structure preserving transformation. We always stay in the same category"). Can someone help?

I believe homomorphism is a subset of endomorphism. So a function that turns an array into another array of different length would be endomorphic (since it maintains the same type), but not homomorphic since it has a different structure (a different set of keys).

The other way around. A homomorphism is a structure-preserving map between two arbitrary objects, whereas an endomorphism is a homomorphism where the source and target objects coincide.

Re: Folding Promises in JavaScript

#36
post #12

I can't quite understand the difference between endomorphism ("input and output of the transformer must be from the same category") and homomorphism ("structure preserving transformation. We always stay in the same category"). Can someone help?

Endomorphism has less implied structure. Lots of dumb things are endomorphisms. Homomorphism implies "structure preservation" which can make it more specific.

I'm surprised to read this coming from you.

Re: Folding Promises in JavaScript

#37
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 :)

A nice use case for sure. Seems possible with some kind of iterator/generator wrapper rather than the mess in the OP however.

Re: Folding Promises in JavaScript

#38
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…

> not all monads support a coalescing operation like Promise.all.

Actually, they do. Haskell calls it sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) [1]

It works by consuming the structure outside the monad and rebuilding it inside. A possible implementation specialized for lists is

  sequence [] = return []
  sequence (h:t) = do
    h' 
[1] http://hackage.haskell.org/package/base-4.10.0.0/docs/Prelud...

Re: Folding Promises in JavaScript

#40
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.

I feel like the functional code you wrote was written to intentionally obfuscate what is being done. For instance, composing a bunch of methods inline doesn't have any utility for it unless you define what compose(xor, lol, rofl) really means.

Ideally this is how it should be written for maximum readability.

  things
  |> pluck('bar')
  |> map(xor)
  |> map(lol)
  |> map(rofl)
  |> reduce(differenceWith('id')

The code is written equally well without using pipe operator but the proposal to introduce it is in works [1].

Here is it using lodash (not even lodash-fp), and this is going to do a single for loop when executing because this is lazy.

  _.chain(things)
   .pluck('bar')
   .map(_.xor)
   .map(_.lol)
   .map(_.rofl)
   .reduce(_.differenceWith('id'))
   .value();
It's no less readable than the code you'd write using using unfolded transformations.

1. https://github.com/tc39/proposal-pipeline-operator

Post reply on HN