TITLE: Two Patterns Dealing with Side Effects AUTHOR: Eugene Wallingford DATE: June 13, 2008 3:55 PM DESC: ----- BODY: I ran across a pattern today that reminded of another I encountered while at ChiliPLoP. Both help developers deal with side effects, changes to a program's state. Let me share these patterns with you all, with a common explanation of their value. Most programs written these days are in a style where setting and changing the values of one or more variables, via a sequence of imperative statements. Side effects are a common source of programmers' misunderstanding when reading code. A program can change a variable's state almost anywhere, and that makes reading any bit of code uneasy: "Do I really know what this variable means right now?" Using only local variables only in the context of a small procedure is one way to localize effects. Even still, problems can arise. I won't try write full patterns for these. I'll write short patlets and give you links to the articles I read, which do a good job talking about the ideas. Mutual Recursion with Side Effects In Solving Every Sudoku Puzzle, Peter Norvig builds a Python program for the title task. About 40% of the way in, he says:
If you have two mutually-recursive functions that both alter the state of an object, try to move almost all the functionality into just one of the functions. Otherwise you will probably end up duplicating code.
Duplicate code is usually a bad thing, because it creates a problem for programmers keeping the copies in sync. Duplicate code that modifies state is especially bad, because it brings in the extra complication of making another procedure harder to understand. Side Effects and Python's Default Parameters Coincidentally, the second pattern involves Python, too. This time the pattern is Python-specific, addressing an issue with a language feature. Context: You are writing a procedure with a default parameter. Problem: The procedure needs to modify the default parameter. Python evaluates a default parameter's initial value only on the first call to the procedure. Solution: Whenever the parameter is missing, initialize it within the method. Tim Ottinger gives his implementation technique in Python's Mutable Default Problem:
def function( item, stuff=None ):
   stuff = stuff or []
   # ... modify stuff, etc.
This pattern allows the user to take advantage of the default parameter when he has no collection to send. It does so by following a principle laid out in the article Ottinger references: In Python, "don't use mutable objects as function defaults." This pattern may not be Python-specific, because there may be other languages with this initialize-once behavior. It seems like a bug to me, not a feature, but I'm not a Python programmer and so can't speak authoritatively. But I am glad that Ruby doesn't do this. ~~~~~ Postscript: While preparing this article, I learned something new about Ruby, unrelated to this issue. It is possible to extract from a class a new class that has a subset of the original class's protocol. Very nice indeed!) -----