The Iterate-and-Mutate Antipattern
April 26, 2020
Names are powerful things. To name something is to control it. For years, I’ve been cautioning friends and colleagues about the following, which I consider a code smell:
enabled_users = 
This code can be dramatically improved with many functional methods, in this case, a simple filter:
for user in users: if user.enabled: enabled_users.append(user)
The part that makes me narrow my eyes, and the way you can identify this, is setting a variable to a null-y value, then opening up a for loop. I’ll go into why I consider this bad practice in this article.
Until 3 days ago, I had no name for this pattern. Since Robb Shecter’s post, I have one: Iterate-and-mutate.
Every language is C (and other lies)
Programming languages aren’t just ways to communicate instructions to machines, the are frameworks for thought.In natural languages, this is called the Sapir–Whorf hypothesis Every language (nearly) supports
if statements and
for loops, so it is easy to solve your programming problems with these constructs. However, it’s NOT easy to read this code after it has been written.
We’ve all seen nested
You get the idea, it’s a famous way of writing spaghetti code. To understand the result of the
for loop, the whole body must be inspected. Whoever looks at your code next must read many lines of code before they understand what is happening, because it can execute arbitary, mutating, side-effecting code.
Think about it
If you were to analyse the flow and swap out
fors with higher-level alternatives, they will more readable. Lets look at my toy example above: Switching the filtering
for loop with the
filter function, allows the reader a hint to what KIND of iteration we are doing.
enabled_users = filter(users, is_user_enabled)
Immediately they can reason more about the code, they know that:
- the new collection will have up to N itemsWhere N is the size of the original collection,
usersin my example
- it will be a subset of the original collection
- with some elements filtered out by some test codeThe well-named function
If we’d used a
for loop, the reader would know that it’s a
for loop. Thanks, I hate it.
Conclusion and Invocation
Once you are aware of the iterate-and-mutate pattern, you’ll be able to think more critically at what kind of problems you’re solving. Nearly all problems we face as programmers are iteration problems.
fors don’t help us much, we need to subcategorise. You’ll start using not just functional methods more,Such as
filter, and list comprehensions but the other high-level features of your language: Higher-order functions, closures, recursion, fluent interfaces, dependant types - OH MY!
In short, you might start enjoying again the great features that made you learn your language in the first place.