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:
filter(users, is_user_enabled)

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 ifs and fors
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 ifs and 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:

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 map, 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.

The Iterate-and-Mutate Antipattern - April 26, 2020 - Tristram Oaten