-
Notifications
You must be signed in to change notification settings - Fork 13
/
04.02-Invest-In-Abstraction.txt~
69 lines (57 loc) · 3.95 KB
/
04.02-Invest-In-Abstraction.txt~
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
4.2 Invest in Abstraction
If brevity is the soul of wit, it is also, along with efficiency, the essence of good
software. The cost of writing or maintaining a program increases with its length.
All other things being equal, the shorter program is the better.
From this point of view, the writing of utilities should be treated as a capital
expenditure. By replacing find-books with the utility find2, we end up with
just as many lines of code. But we have made the program shorter in one sense,
because the length of the utility does not have to be charged against the current
program.
It is not just an accounting trick to treat extensions to Lisp as capital expenditures.
Utilities can go into a separate file; they will not clutter our view as we’re
working on the program, nor are they likely to be involved if we have to return
later to change the program in some respect.
As capital expenditures, however, utilities demand extra attention. It is especially
important that they be well-written. They are going to be used repeatedly,
so any incorrectness or inefficiency will be multiplied. Extra care must also go
into their design: a new utility must be written for the general case, not just for the
problem at hand. Finally, like any capital expenditure, we need not be in a hurry
about it. If you’re thinking of spinning off some new operator, but aren’t sure
that you will want it elsewhere, write it anyway, but leave it with the particular
program which uses it. Later if you use the new operator in other programs, you
can promote it from a subroutine to a utility and make it generally accessible.
The utility find2 seems to be a good investment. By making a capital outlay
of 7 lines, we get an immediate savings of 7. The utility has paid for itself in the
first use. A programming language, Guy Steele wrote, should “cooperate with
our natural tendency towards brevity:”
. . .we tend to believe that the expense of a programming construct
is proportional to the amount of writer’s cramp that it causes us (by
“belief” I mean here an unconscious tendency rather than a fervent
conviction). Indeed, this is not a bad psychological principle for
language designers to keep in mind. We think of addition as cheap
partly because we can notate it with a single character: “+”. Even if
we believe that a construct is expensive, we will often prefer it to a
cheaper one if it will cut our writing effort in half.
In any language, the “tendency towards brevity” will cause trouble unless it is
allowed to vent itself in new utilities. The shortest idioms are rarely the most
efficient ones. If we want to know whether one list is longer than another, raw
Lisp will tempt us to write
(> (length x) (length y))
If we want to map a function over several lists, we will likewise be tempted to join
them together first:
(mapcar fn (append x y z))
Such examples show that it’s especially important to write utilities for situations
we might otherwise handle inefficiently. A language augmented with the right
utilities will lead us to write more abstract programs. If these utilities are properly
defined, it will also lead us to write more efficient ones.
A collection of utilities will certainly make programming easier. But they can
do more than that: they can make you write better programs. The muses, like
cooks, spring into action at the sight of ingredients. This is why artists like to
have a lot of tools and materials in their studios. They know that they are more
likely to start something new if they have what they need ready at hand. The same
phenomenon appears with programs written bottom-up. Once you have written a
new utility, you may find yourself using it more than you would have expected.
The following sections describe several classes of utility functions. They do
not by any means represent all the different types of functions you might add to
Lisp. However, all the utilities given as examples are ones that have proven their
worth in practice.