Hacker News new | ask | show | jobs
by hinkley 2472 days ago
I'm finding that in Javascript, I really enjoy map() and filter(), but map() caused some friction on code reviews at one place, from someone I don't think had any FP background. The are best when they are one liners, of the form .map((val) => someFunction(val)) or .filter((val) => val.length > 1)

reduce() on the other hand is always illegible to me. I get pretty grumpy when I am 'forced' to use a reduce because the code calls for it. It just looks like I'm trying to write obfuscated code.

Often I'll just unroll it to a forEach.

This code structure in your example reminds me of some Python code I was reading recently (Norvig's Sudoku solver). Putting the conditional at the end of the line fights the way humans process data. Quite often we are trying to filter lines of code that could be involved in a problem and saying things like "do an action (if this condition is true)" increases the amount of short term memory I have to use to process the function. That's bad ergonomics.

4 comments

"but map() caused some friction on code reviews at one place"

Someone not familiar or comfortable with "map" should not be working as a professional programmer today. Most languages now support "map" or something very similar.

Try to move to a different team or different company with actual professional developers.

> Someone not familiar or comfortable with "map" should not be working as a professional programmer today.

I completely disagree - you are measuring the quality of a programmer on a single dimension.

I have worked with very weak programmers that produce gold e.g. great at pulling a team together, great at producing outcomes that clients love, great at focusing on features that sell.

I have also worked with great programmers that just stick to what they know - they don't know map() because they concentrate on being productive rather than continually chasing the next greatest language or library.

I have also worked with technically awesome programmers that produce absolute crap e.g. struggle to communicate, struggle to make good engineering compromises, struggle to understand requirements. One smart guy was so creepy no women could work with him which meant he was actually pretty useless - I saw one friend who worked as a consultant there hide under her desk to avoid him!

I almost fully agree. A professional programmer, how can such a person not know about stuff like map, filter and reduce? It can only happen, when they never cared to learn programming languages, paradigms or concepts of various kinds. This would betray an attitude of not continuing to learn. Even, if they have not come into contact with other programming concepts, how can any professional not have heard anything about map-reduce stuff at some point somewhere? Seems very unlikely to happen without learning-resistance or disinterest towards learning or informing oneself.

However, I would exclude junior software developers from this, as they might have just come from university, where they might not have learned about this at all, depending on the university. Still computer programming is then what they do as "profession", so we would have to count them as "professionals".

That was more of a "it's not universal" comment. Sometimes the right solution is self obvious, other times it needs PR.

If I write a piece of code so others don't have to, then it's a service I'm providing. If they don't 'get' the code then the problem is not always with them. It's important to watch for patterns in the questions or complaints you get. There are often multiple acceptable ways to solve the same problem and everything goes smoother if the one you use doesn't trip people up.

In this case I pointed him to some documentation on filter and map.

I've been noodling with Julia recently and the dot-syntax is really surprisingly ergonomic for transforming hunks of data. It has the benefit of making vectorization easier for the compiler, but I enjoy the syntax.

https://docs.julialang.org/en/v1/manual/functions/#man-vecto...

That's a cool trick but I'd like an operator with more pixels for that behavior.

When I used to track new languages, I ran into one where the . was implicit. You could change a member of an object from a single value to an array and it would iterate over all of the values. So you could do an information architecture that was 1:1 and change to 1:many later and things would still work.

If you think of 'reduce' as instead 'accumulating' a value, then it takes a function that adds a single element to the accumulation, and a base accumulation to use if the list is empty, and a list, and returns an accumulation of all of the elements of the list in a directional (in this case right-to-left) order.

(accumulate plus 0 lst) is equivalent to (sum lst)

(accumulate multiply 1 lst) is equivalent to (product lst)

(accumulate (lambda (x acc) (cons (fn x) acc)) '() lst) is equivalent to (map fn lst)

(accumulate (lambda (x acc) (if (fn x) (cons x acc) acc))) '() lst) is equivalent to (filter fn lst)

and so forth. The essential insight is that reduce/fold/accumulate reduces the problem of accumulation to a base accumulation and a function that only has to add a single item (i/o)nto the accumulated value. Using them to directionally processes a container is idiomatic in a functional style.

C++ even calls it std::accumulate. (There’s a std::reduce in C++17, but it’s just std::accumulate with the restriction that the operation is commutative.)
> reduce() on the other hand is always illegible to me.

I used it recently in ruby to write an sql query using Rails' ORM and it seemed quite nice to me. Something like:

  foos.to_enum.with_index.reduce(initial_query) do |query, (foo, i)|
    query.joins(...).where(...)
  end