Hacker News new | ask | show | jobs
by davidashe 1559 days ago
Now that generics are in beta, here's a library for those who want ergonomic slice/map wrappers that make chainable operations easy.

Or, a gateway drug for ECMAscripters who can't drop their `.map(x => y).filter(x => y).reduce(x => y)` habit.

2 comments

Yep, nobody pipes data through any processing in say Haskell or Clojure.
That habit makes zero sense. Reduce already is a map and filter and one, why do you need to loop it 3 times? Reduce itself is awful to begin with.

https://twitter.com/jaffathecake/status/1213077702300852224

it's a readable, maintainable composable functional pattern that unfortunately scales badly in JS because the methods are all eager methods; there are libraries with lazy versions that return generators so that chaining them produces a pipeline that does one loop rather than one per chained operation, though, which most sensible languages do, or at least support, out of the box.

Still, if you know you’ll have a small working set, and you don't what the extra deependency, there's lots of cases where bet readability, composability, and maintainability wins over efficiency.

> Reduce already is a map and filter and one, why do you need to loop it 3 times?

Because being explicit about intent is important. Map means "transforming each element of the collection", filter means "keeping only some elements of the collection". With both, you only have to write what happens to one element, and it will happen to the whole collection. This makes code easier to read. You don't have to spend energy to understand if the loop is only a transformation, or also filtering. Since you chain them, you can easily isolate each transformation, which makes code easier to read and easier to test.

> Reduce itself is awful to begin with.

I don't really understand what's supposed to be awful about reduce. It's just another form of for loop. I don't see people arguing that for loops are awful. The thread you linked is just someone that's biased against reduce for some reason that I don't quite understand. Reduce makes explicit that when using a for loop and accumulating a result, you need both a base case, and what to do when going from n to n+1. Again, this allows you to isolate the "going from n to n+1" part easily. Recursion itself is great for some problems.

> what to do when going from n to n+1

You mention the only worthwhile exception: sums and other 3-character operation.

If you’re using reduce to construct objects you’re just better off with a for loop. Having a random awkward named function that only makes sense when plugged into reduce is not any better than just have a function that includes the loop itself:

    - newArray = array.reduce(operation, [])
    + newArray = operation(array)
If you’re used to having infinite chains of loops then of course that’s not going to work.

The problem is that reduce can do anything and most people use it to do anything. It has no advantage over regular for loops unless you’re proficient with real functional programming (if you use forEach() in JavaScript, you’re not)

> With both, you only have to write what happens to one element, and it will happen to the whole collection. This makes code easier to read.

Filter and map are ok. Filter, map and reduce are not, at least not in JavaScript. Try writing the equivalent for loop and you’ll find that it’s just as simple to follow.