Derek Jones from The Shape of Code
Exercises in Programming Style by Cristina Lopes is an interesting little book.
The books I have previously read on programming style pick a language, and then write various programs in that language using different styles, idioms, or just following quirky rules, e.g., no explicit loops, must use sets, etc. “Algorithms in Snobol 4” by James F. Gimpel is a fascinating read, but something of an acquired taste.
EPS does pick a language, Python, but the bulk of the book is really a series of example programs illustrating a language feature/concept that is central to a particular kind of language, e.g., continuation-passing style, publish-subscribe architecture, and reflection. All the programs implement the same problem: counting the number of occurrences of each word in a text file (Jane Austin’s Pride and Prejudice is used).
The 33 chapters are each about six or seven pages long, and contain a page or two or code. Everything is very succinct, and does a good job of illustrating one main idea.
While the first example does not ring true, things quickly pick up and there are lots of interesting insights to be had. The first example is based on limited storage (1,024 bytes), and just does not make efficient use of the available bits (e.g., upper case letters can be represented using 5-bits, leaving three unused bits or 37% of available storage; a developer limited to 1K would not waste such a large amount of storage).
Solving the same problem in each example removes the overhead of having to learn what is essentially housekeeping material. It also makes it easy to compare the solutions created using different ideas. The downside is that there is not always a good fit between the idea being illustrated and the problem being solved.
There is one major omission. Unstructured programming; back in the day it was just called programming, but then structured programming came along, and want went before was called unstructured. Structured programming allowed a conditional statement to apply to multiple statements, an obviously simple idea once somebody tells you.
When an if-statement can only be followed by a single statement, that statement has to be a goto
; an if
/else
is implemented as (using Fortran, I wrote lots of code like this during my first few years of programming):
IF (I .EQ. J)
GOTO 100
Z=1
GOTO 200
100 Z=2
200
Based on the EPS code in chapter 3, Monolithic, an unstructured Python example might look like (if Python supported goto
):
for line in open(sys.argv[1]):
start_char = None
i = 0
for c in line:
if start_char != None:
goto L0100
if not c.isalnum():
goto L0300
# We found the start of a word
start_char = i
goto L0300
L0100:
if c.isalnum():
goto L0300
# We found the end of a word. Process it
found = False
word = line[start_char:i].lower()
# Ignore stop words
if word in stop_words:
goto L0280
pair_index = 0
# Let's see if it already exists
for pair in word_freqs:
if word != pair[0]:
goto L0210
pair[1] += 1
found = True
goto L0220
L0210:
pair_index += 1
L0220:
if found:
goto L0230
word_freqs.append([word, 1])
goto L0300
L0230:
if len(word_freqs) <= 1:
goto L0300:
# We may need to reorder
for n in reversed(range(pair_index)):
if word_freqs[pair_index][1] <= word_freqs[n][1]:
goto L0240
# swap
word_freqs[n], word_freqs[pair_index] = word_freqs[pair_index], word_freqs[n]
pair_index = n
L0240:
goto L0300
L0280:
# Let's reset
start_char = None
L0300:
i += 1
If you do feel a yearning for the good ol days, a goto package is available, enabling developers to write code such as:
from goto import with_goto
@with_goto
def range(start, stop):
i = start
result = []
label .begin
if i == stop:
goto .end
result.append(i)
i += 1
goto .begin
label .end
return result