Turning Your Code Inside Out

If I gave this assignment to a class of novice programmers:

Write a C program to sum the elements of an array and display the results. Include five test cases.

I'd expect multiple people would come up with a function like this:

void sum_array(int array[], int size) { int sum = 0; for (int i = 0; i < size; i++) { sum += array[i]; } printf("the sum of the array is %d

", sum); }

There's a cute new programmer-ism in that solution: displaying the output is built into sum_array instead of returning the sum and printing it elsewhere. Really, it's hard to see why that one extra line is a bad idea, at least up front. It prevents duplication of the printf call, which is good, right? But tack on an extra requirement such as "Use your array summing function to compute the total sum of three arrays," and there will be an "Ohhhhh, I don't want that print in there" moment.

The design error was obvious in this example, but it crops up in other cases where it isn't so immediately clear.

Let's say we're writing a video game and there's a function to spawn an attacker. To alert the player of the incoming danger, there's a sound accompanying the appearance of each new attacker, so it makes sense to play that sound inside new_attacker .

Now suppose we want to spawn five attackers at the same time by calling new_attacker in a loop. Five attackers are created as expected, but now five identical sounds are starting during the same frame. Those five sounds will be perfectly overlaid on top of each other, at best sounding five times louder than normal and at worst breaking-up because the audio levels are too high. As a bonus, we're taking up five audio channels so the player can hear this mess.

The solution is conceptually the same as the sum_array example: take the sound playing out of new_attacker and let the caller handle it. Now there's a single function call to start a sound followed by a loop that creates the attackers.

Why am I bothering to talk about this?

This method of turning your code inside out is the secret to solving what appear to be hopelessly state-oriented problems in a purely functional style. Push the statefulness to a higher level and let the caller worry about it. Keep doing that as much as you can, and you'll end up with the bulk of the code being purely functional.

(If you liked this, you might enjoy Purely Functional Retrogames.)

permalink March 23, 2012

previously