Hacker News new | ask | show | jobs
by megawatthours 3216 days ago
Something I see often and is a huge code smell to me is not using the most restrictive form of iteration.

If you see collection.map(...) you know that each iteration is simply a pure function from original element to transformed element, which is an immense help when reading the code.

If you can use only map / filter / takeWhile / join etc to express what you are doing, use those! If not, try and just use reduce / foreach. If not, try and just use for. Only use while if nothing else works!

2 comments

> If you see collection.map(...) you know that each iteration is simply a pure function from original element to transformed element, which is an immense help when reading the code.

You'd think so, but I've had colleagues who managed to fuck that up and use map or list comprehension solely for side-effects.

I saw some code like this:

    def update(): Try[Unit] = {
      parser.parse(...).map(result => updateState(result))
    }
And I thought it was abusing the map() call for side effects. However, it is still shorter than writing it out as follows:

    def update(): Try[Unit] = {
      parser.parse(...) match {
        case Success(result) =>
          updateState(result)
          Success(())
        case f@Failure(_) =>
          f
      }
   }
So I didn't have a strong opinion either way since semantically both do the same (and in the case of Scala, the first one is potentially more performant since it relies on the JVM doing virtual dispatch as opposed to calling unapply() and matching, not to mention potentially less garbage being generated).
Even Excalibur can be used to mince garlic, and even a supercomputer can be used to play Zork.
Yeah I mean my point is "trust but verify", I love restricted iteration construct, but just because they're being used does not mean they're being used "properly" unless the language ensures it.
This. I've seen FP features (and incidentally OOP features as well) misused so hard, I'm thankful for every plain loop (or struct for that matter).
What is the "most restrictive" form? The answer to this question is highly context dependent (for example, programming language / architectural framework) and expensive to give. Remember that everything has a cost. And especially overzealous formalism.

Personally I find simple C index-based for loops consistent and refreshing. And it's typically not a huge deal. If it is, the procedure might be doing too many things at once. (But yes, I use simple "for x in y" style loops in Python or C++ when they make the lion's share of the loops).

Many different types of loops in a single file, over a single datastructure, always remind me of odd syntax highlighting (for example in vim) in so many different colors that it's only a distraction. I don't care to make so many distinctions. I try to focus on the distinctions that we have to make to get a program done.

Map-style iteration carries more semantic information than a C-style index based loop. An index based loop might be doing anything with the data being iterated over. When you do collection.map, already at first glance you get an idea about what the code is doing.
Yep - and nobody cares. Write clean code instead. Much harder than simply changing the looping style.