I'm James Hague, a recovering programmer who has been designing video games since the 1980s. This is Why You Spent All that Time Learning to Program and The Pure Tech Side is the Dark Side are good places to start.
Where are the comments?
Turning Your Code Inside OutIf 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:
sum_arrayinstead 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
printfcall, 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
Now suppose we want to spawn five attackers at the same time by calling
new_attackerin 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_arrayexample: take the sound playing out of
new_attackerand 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.)