. 3
( 13)


formulas called expressions. The formulas are algebraic in the sense that they constant
involve variables as well as constants. By combining variables and constants with operator
appropriate mathematical operations, a programmer can specify an amazing parentheses
variety of things with comparative ease. sqrt
We have already seen many examples of expressions; our goal now is to
make a more systematic study of what is possible. The general idea is that an
expression is either a variable (e.g., ˜x1 ™ ) or a constant (e.g., ˜20™ ), or it consists
of an operator (e.g., ˜+™ ) together with its operands (e.g., ˜x1 + 20™ ). The
operands are, in turn, expressions built up in the same way, perhaps enclosed in
parentheses. For example, ˜(x1 +20)/(x2 ’20)™ is an expression that stands for the
quotient of two subexpressions. It is possible to concoct extremely complicated
algebraic expressions, but even the most intricate constructions are built from
simple parts in simple ways.
Mathematicians spent hundreds of years developing good ways to write
formulas; then computer scientists came along and upset all the time-honored
traditions. The main reason for making a change was the fact that computers
¬nd it di¬cult to deal with two-dimensional constructions like
x1 + 20
a2 ’
+ b.
x2 ’ 20 3
One-dimensional sequences of tokens are much easier to input and to decode;
hence programming languages generally put such formulas all on one line, by
inserting parentheses, brackets, and asterisks as follows:
will understand this formula, but it also accepts a notation that is
shorter and closer to the standard conventions of mathematics:
(x1+20)/(x2-20)+sqrt(a**2-2/3sqrt b).
We observed in the previous chapter that allows you to write ˜x2™
instead of ˜x[2]™; similarly, you can write ˜2x™ instead of ˜2*x™ and ˜2/3x™ instead
of ˜(2/3)*x™. Such operations are extremely common in programs,
hence the language has been set up to facilitate them. On the other hand, -
doesn™t free you from all the inconveniences of computer languages; you
must still write ˜x*k™ for the product of x times k, and ˜x[k]™ for the variable
x subscripted by k, in order to avoid confusion with the su¬xed variable ˜x.k™.
We learned in the previous chapter that there are eight types of variables:
numeric, boolean, string, and so on. The same types apply to expressions; -
deals not only with numeric expressions but also with boolean expressions,
string expressions, and the others. For example, ˜(0, 0) . . (x1 , y1 )™ is a path-
valued expression, formed by applying the operator ˜. .™ to the subexpressions
˜(0, 0)™ and ˜(x1 , y1 )™; these subexpressions, in turn, have values of type “pair,”
and they have been built up from values of type “numeric.” Each operation
60 Chapter 8: Algebraic Expressions

produces a result whose type can be determined from the types of the operands; order of operations
furthermore, the simplest expressions (variables and constants) always have a magnets
de¬nite type. Therefore the machine always knows what type of quantity it is braces
dealing with, after it has evaluated an expression.
If an expression contains several operators, has to decide
which operation should be done ¬rst. For example, in the expression ˜a ’ b + c™
it is important to compute ˜a ’ b™ ¬rst, then to add c; if ˜b + c™ were computed
¬rst, the result ˜a ’ (b + c)™ would be quite di¬erent from the usual conventions
of mathematics. On the other hand, mathematicians usually expect ˜b/c™ to
be computed ¬rst in an expression like ˜a ’ b/c™; multiplications and divisions
are usually performed before additions and subtractions, unless the contrary is
speci¬cally indicated by parentheses as in ˜(a ’ b)/c™. The general rule is to
evaluate subexpressions in parentheses ¬rst, then to do operations in order of
their “precedence”; if two operations have the same precedence, the left one is
done ¬rst. For example, ˜a ’ b/c™ is equivalent to ˜a ’ (b/c)™ because division
takes precedence over subtraction; but ˜a ’ b + c™ is equivalent to ˜(a ’ b) + c™
because left-to-right order is used on operators of equal precedence.
It™s convenient to think of operators as if they are tiny magnets that
attract their operands; the magnets for ˜—™ and ˜/™ are stronger than the magnets
for ˜+™ and ˜’™, so they stick to their operands more tightly and we want to
perform them ¬rst.
distinguishes four (and only four) levels of precedence. The
strongest magnets are those that join ˜2™ to ˜x™ and ˜sqrt™ to ˜b™ in expressions like
˜2x™ and ˜sqrt b™. The next strongest are multiplicative operators like ˜—™ and ˜/™;
then come the additive operators like ˜+™ and ˜’™. The weakest magnets are
operators like ˜. .™ or ˜<™. For example, the expression
a + sqrt b/2x < c
is equivalent to the fully parenthesized formula
a + (sqrt b)/(2x) < c.

Insert parentheses into the formula ˜z1+z2..z3/4*5..z6-7*8z9™, to show ex-
plicitly in what order will do the operations.
High-school algebra texts often avoid parentheses inside of parentheses by
using braces and brackets. Therefore many people have been trained to write

{a + [(sqrt b)/(2x)]} < c

instead of the fully parenthesized formula above. However, professional mathematicians
usually stick to only one kind of parentheses, because braces and brackets have other
meanings that are more important. In this respect is like the professionals:
It reserves curly braces ˜{}™ and square brackets ˜[]™ for special purposes, so you should
not try to substitute them for parentheses.
Chapter 8: Algebraic Expressions 61

If you really want alternatives to parentheses, there is actually a way to get delimiters
division of numeric tokens
them. You can say, for example,
delimiters [[ ]]; delimiters {{ }} scrollmode
after which double brackets and braces can be used in formulas like scantokens
{{a+[[(sqrt b)/(2x)]]}}<c. message
The symbolic token ˜{{™ has no relation to ˜{™, and it has no primitive meaning, hence
you are free to de¬ne it in any way you like; the delimiters command de¬nes a new
pair of delimiters. In formulas with mixed delimiters as de¬ned here, will
check that ˜[[™ matches only with ˜]]™, ˜{{™ only with ˜}}™, and ˜(™ only with ˜)™; thus
you can more easily detect errors in large expressions. However, it™s usually unnecessary
to have any delimiters other than parentheses, because large expressions are rare, and
because the rules of operator precedence make most parentheses super¬‚uous.

If you™re reading this chapter carefully, you may be thinking, “Hey wait!
Isn™t there a contradiction? A minute ago I was told that ˜2/3x™ stands for
˜(2/3)*x™, but now the rules of precedence appear to state that ˜2/3x™ really
stands for ˜2/(3x)™. What gives?” Indeed, you have an excellent point; but
there is no contradiction, because of another rule that hasn™t been mentioned
yet. When two numeric tokens are divided, the magnetism of ˜/™ is stronger
than usual; in this case ˜/™ has the same precedence as the implied multiplication
operator in ˜3x™. Hence the operations in ˜2/3x™ are carried out from left to right,
as stated previously. (This is a good rule because it is almost always what a
programmer wants. However, one should bear in mind that ˜a/3x™
means ˜a/(3x)™ when a is not a numeric token.)
Because of the rule in the previous paragraph, the programs
in this book often say ˜ 3 x™ for what would be typed ˜2/3x™ in a ¬le. Such built-up
fractions are never used except when the numerator and denominator are both
numbers; a construction like ˜a/3x™ will always be rendered as ˜a/3x™, not ˜ 3x ™.
knows how to do dozens of operations that haven™t been
mentioned yet in this book. Let™s take a look at some of them, so that we will
know they are available in case of need. It will be most instructive and most
fun to learn about expressions by interacting with the computer; therefore you
should prepare the following short ¬le, called expr.mf:
string s[]; s1="abra";
path p[]; p1=(0,0)..(3,3); p2=(0,0)..(3,3)..cycle;
tracingonline:=1; scrollmode;
forever: message "gimme an expr: "; s0:=readstring;
show scantokens s0; endfor
You don™t need to understand what™s in expr.mf when you read this chapter for
the ¬rst time, because the ¬le uses in ways that will be explained
carefully later. But here is a translation, in case you™re curious: Line 1 declares all
variables of the form sk to be strings, and sets s1 to the value "abra". Line 2 declares
all variables of the form pk to be paths, and sets p1 and p2 to simple example paths.
62 Chapter 8: Algebraic Expressions

Line 3 tells to print diagnostic information online, i.e., on the terminal as online
log ¬le
well as in the log ¬le; it also establishes ˜scrollmode™, which means that the computer
won™t stop after error messages. Lines 4 and 5 set up an in¬nite loop in which - arithmetic
reads an expression from the terminal and shows the corresponding value. epsilon

If you start and type ˜expr™ when it asks for an input ¬le
name, it will read the ¬le expr.mf and then it will say ˜gimme an expr™. Here™s
where the fun starts: You can type any expression, and will compute
and display its value. Try it; type ˜2+2™ and return , obtaining the value ˜>> 4™.
Isn™t that amazing? Here are some more things to try:
You type And the result is
1.2-2.3 -1.1
1.3-2.4 -1.09999
1.3*1000 1300.00305
2.4*1000 2399.9939
3/8 0.375
.375*1000 375
1/3 0.33333
1/3*3 0.99998
0.99999 0.99998
1-epsilon 0.99998
1/(1/3) 3.00005
1/3.00005 0.33333
.1*10 1.00006
1+4epsilon 1.00006
These examples illustrate the small errors that occur because does
“¬xed binary” arithmetic using integer multiples of 65536 . The result of 1.3 ’ 2.4

is not quite the same as ’1.1, because 1.3 is a little bit larger than 13 and 2.4
is a little smaller than 24 . Small errors get magni¬ed when they are multiplied
by 1000, but even after magni¬cation the discrepancies are negligible because
they are just tiny fractions of a pixel. You may be surprised that 1/3 times 3
comes out to be .99998 instead of .99999; the truth is that both 0.99999 and
0.99998 represent the same value, namely 65535 ; displays this value
as 0.99998 because it is closer to .99998 than to .99999. Plain
de¬nes epsilon to be 65536 , the smallest representable number that is greater
than zero; therefore 1-epsilon is 65535 , and 1+4epsilon is 65540 .
65536 65536

You type And the result is
4095.99998 (with error message)
infinity 4095.99998
32767.99998 (with error message)
Chapter 8: Algebraic Expressions 63

infinity+epsilon 4096 enormous number
100*100 10000 mediation
.1(100*100) 1000.06104 divide
(100*100)/3 3333.33333
will complain that an ˜Enormous number has been reduced™ when
you try to introduce constants that are 4096 or more. Plain de¬nes
in¬nity to be 4096 ’ epsilon , which is the largest legal numeric token. On
the other hand, it turns out that larger numbers can actually arise when an
expression is being evaluated; doesn™t worry about this unless the
resulting magnitude is at least 32768.
If you try ˜100*100/3™ instead of ˜(100*100)/3™, you get ˜3333.33282™. Why?
Sometimes will compute things more accurately than you would
expect from the examples above, because many of its internal calculations are
done with multiples of 2’28 instead of 2’16 . For example, if t = 3 the result of ˜1/3t™
will be exactly 1 (not 0.99998); the same thing happens if you write ˜1/3(3)™.
Now let™s try some more complicated expressions, using unde¬ned vari-
ables as well as constants. (Are you actually trying these examples, or are you
just reading the book? It™s far better to type them yourself and to watch what
happens; in fact, you™re also allowed to type things that aren™t in the book!)
You type And the result is
b+a a+b
a+b a+b
b+a-2b a-b
2(a-b+.5) 2a-2b+1
.5(b-a) -0.5a+0.5b
.5[a,b] 0.5a+0.5b
1/3[a,b] 0.66667a+0.33333b
0[a,b] a
a[2,3] a+2
t[a,a+1] t+a
b (with error message)
b (with error message)
has a preferred way to arrange variables in order when they are
added together; therefore ˜a + b™ and ˜b + a™ give the same result. Notice that
the mediation construction ˜.5[a, b]™ speci¬es a number that™s halfway between a
and b, as explained in Chapter 2. does not allow you to multiply
two unknown numeric quantities together, nor can you divide by an unknown
numeric; all of the unknown expressions that works with must be
64 Chapter 8: Algebraic Expressions

“linear forms,” i.e., they must be sums of variables with constant coe¬cients, linear forms
plus an optional constant. (You might want to try typing ˜t[a,b]™ now, in order square roots
to see what error message is given.) **
You type And the result is false

sqrt 2 1.41422
sqrt 100 10
sqrt 100*100 1000
sqrt(100*100) 100
sqrt 100(100) 100
sqrt sqrt 100(100) 10
sqrt .01 0.09998
0.09998**2 0.01
2**1/2 1.41422
sqrt 2**2 2
0 (with error message)
sqrt -1
a (with error message)
sqrt a
Since sqrt has more “magnetism” than *, the formula sqrt 100*100 is evaluated
as (sqrt 100)*100; but in ˜sqrt 100(100)™ the 100(100) is computed ¬rst. The
reason is that ˜(sqrt 100)(100)™ isn™t a legal expression, so the operations in
˜sqrt 100(100)™ must be carried out from right to left. If you are unsure about
the order of evaluation, you can always insert parentheses; but you™ll ¬nd that
™s rules of precedence are fairly natural as you gain experience.
Is ˜sqrt 2**2™ computed as ˜(sqrt 2)**2™ or as ˜sqrt(2**2)™ ?
Some expressions have ˜true™ or ˜false™ values, instead of
numbers; we will see later that they can be used to adapt programs
to special conditions.
You type And the result is
0<1 true
0=1 false
a+1>a true
false (with error message)
"abc"<="b" true
"B">"a!" false
"b">"a?" true
(1,2)<>(0,4) true
(1,2)<(0,4) false
(1,a)>(0,b) true
Chapter 8: Algebraic Expressions 65

numeric a true not
known a false or
not pen a true ¿=
known "a" and numeric 1 true
(0>1) or (a<a) false relations
a (with error messages)
0>1 or a<a less-than-or-equal-to
The tokens ˜>=™, ˜<=™, and ˜<>™ stand respectively for the relations greater-than- pair
or-equal-to, less-than-or-equal-to, and unequal-to. When strings are compared, pen
uses the order of words in a dictionary, except that it uses ASCII known
code to de¬ne ordering of individual characters; thus, all uppercase letters are min
considered to be less than all lowercase letters. (See Appendix C.) When pairs maximum
of numbers are compared, considers only the x coordinates, unless integers
the x coordinates are equal; in the latter case it compares the y coordinates. The
type of an expression can be ascertained by an expression like ˜pair a™, which is
true if and only if a is a pair. The expression ˜known a™ is true if and only if the
value of a is fully known.
What causes the error messages in ˜0>1 or a<a™ ?
The rest of this chapter is entirely preceded by “dangerous bend” signs, so
you can safely omit it on ¬rst reading (unless you™re hooked and can™t stop).
expressions can include many operations that are less familiar but
still useful. For example, the max and min operations compute the maximum
and minimum of numbers, strings, or pairs:
You type And the result is
max(1,-2,4) 4
min(1,-2,4) -2
max("a","b","ab") "b"
min("a","b","ab") "a"
max((1,5),(0,6),(1,4)) (1,5)
min((1,5),(0,6),(1,4)) (0,6)
max(.5a+1,.5a-1) 0.5a+1
Numbers can be converted to integers in a variety of ways:
You type And the result is
floor 3.14159 3
floor -3.14159 -4
floor -epsilon -1
floor infinity 4095
ceiling 3.14159 4
ceiling -3.14159 -3
66 Chapter 8: Algebraic Expressions

round 3.14159 3 ¬‚oor
greatest integer
round -3.14159 -3 ceiling
least integer
round(1.1,2.8) (1,3)
round(3.5,-3.5) (4,-3) remainder
a+0.5 (with error message)
round a abs
8 mod 3 2
absolute value
-8 mod 3 1 ++
Pythagorean addition
.8 mod .3 0.2
square root
Pythagorean subtraction
The ˜¬‚oor™ operation computes the greatest integer that is less than or equal to its +-+
operand; this quantity is often denoted by x in mathematics texts. Plain
also includes the analogous ˜ceiling™ operation x , which is the least integer greater
than or equal to x. Furthermore, ˜round x™ is the integer nearest to x; plain
computes this by using the formula x + .5 , and applies it to both components of a
pair if a pair is being rounded. The remainder of x with respect to y, written ˜x mod y™,
is calculated by using the formula x ’ y x/y .

You type And the result is
abs -7 7
abs(3,4) 5
length(3,4) 5
3++4 5
300++400 500
181.01933 (with error messages)
sqrt(300**2 + 400**2)
1++1 1.4142
0 ++ -7 7
5+-+4 3

The ˜++™ operation is called Pythagorean addition; a++b is the same thing as a2 + b2 .
Most of the square root operations in computer programs could probably be avoided
if ++ were more widely available, because people seem to want√ square roots primarily
when they are computing distances. Notice that a ++ b ++ c = a2 + b2 + c2 ; we have
the identity (a ++ b) ++ c = a ++ (b ++ c) as √ well as a ++ b = b ++ a. It is better
to use Pythagorean addition than to calculate a2 + b2 , because the computation of
a2 and b2 might produce numbers that are too large even when a ++ b is rather small.
There™s also an inverse operation, √
Pythagorean subtraction, which is denoted by ˜+-+™;
the quantity a +’+ b is equal to a2 ’ b2 .

When the author was preparing these examples he typed ˜0++-7™ and was
surprised to get the answer ˜0™. Why should this not have been a surprise?

(For mathematicians.) Although the Pythagorean addition operation is asso-
ciative and commutative, says that 5++4++2++2 = 7 = 2++2++4++5
yet 2 ++ 4 ++ 5 ++ 2 = 6.99998. Why?
Chapter 8: Algebraic Expressions 67

uses the names ˜sind™ and ˜cosd™ for the trigonometric functions sind
sine and cosine, because ™s operations are designed to deal with
angles expressed in degrees. But it turns out that programmers rarely need to refer sine
to sines and cosines explicitly, because the ˜dir™ and ˜angle™ functions provide most of cosine
what a font designer needs. angle
You type And the result is mexp

sind 30 0.5
cosd 30 0.86603
sind -30 -0.5
cosd 360 1
sind 10 ++ cosd 10 1
dir 30 (0.86603,0.5)
dir -90 (0,-1)
angle(1,1) 45
angle(1,2) 63.43495
angle(1,-2) -63.43495
sind 63.43495 / cosd 63.43495 1.99997
angle up 90
angle left 180
angle(-1000,-epsilon) -180
angle dir 60 60.00008
0 (with error message)

Plain de¬nes ˜dir x™ to be the pair of values (cosd x, sind x); this is a vector,
which points x degrees above the rightward horizon. Conversely, the ˜angle™ operator
determines the angle that corresponds to a given vector.

Logarithms and exponentials are computed with respect to an unusual base,
designed to enhance the accuracy of calculations involving ¬xed-radix numbers
™s range. The values mlog x = 256 ln x and mexp x = ex/256 produce
reasonably good results when x —— y is computed by the formula mexp(y — mlog x).

You type And the result is
mlog 2 177.44568
mexp mlog 2 2
mexp 8 mlog 2 256
mexp 256 2.71828
mlog 2.71828 255.99954
mlog 2.71829 256.00098
15 mlog 2 2661.68518
mexp 2661.68518 32767.99998
32767.99998 (with error message)
mexp 2661.68519
mexp-2661.68519 0.00003
68 Chapter 8: Algebraic Expressions

also generates two ¬‚avors of random numbers. It is very unlikely uniformdeviate
that you will get the particular values shown in the following examples, when
you do the experiment yourself, because the results come out di¬erent each time the xscaled
computer is asked for a new random number (unless you have speci¬ed a “seed value” yscaled
as explained in Chapter 21).

You type And the result might be
uniformdeviate 100 47.4241
uniformdeviate 100 97.28148
uniformdeviate -100 -36.16279
(normaldeviate,normaldeviate) (0.46236,-1.87648)

The value of ˜uniformdeviate 100™ is a random number between 0 and 100; the value
of ˜normaldeviate™ is a normally distributed random number whose mean value is zero
and whose standard deviation is unity. Chapter 21 explains what this means and gives
several applications.

Besides all of these operations on numbers, has a rich collection
of operations on pairs, some of which are indicated in the following examples:

You type And the result is
right (1,0)
(1,2)+(3,4) (4,6)
1/3(3,10) (1,3.33333)
z2-z1 (-x1+x2,-y1+y2)
.2[z1,z2] (0.8x1+0.2x2,0.8y1+0.2y2)
3z (3x,3y)
z scaled 3 (3x,3y)
z xscaled 2 yscaled 1/2 (2x,0.5y)
z shifted (2,3) (x+2,y+3)
z shifted 3right (x+3,y)
z slanted 1/6 (x+0.16667y,y)
z rotated 90 (-y,x)
z rotated 30 (-0.5y+0.86603x,0.86603y+0.5x)
xpart(z rotated 30) -0.5y+0.86603x
ypart(z rotated 30) 0.86603y+0.5x
(3,4) (with error message)
(1,2)zscaled(3,4) (-5,10)
(a,b)zscaled(3,4) (3a-4b,4a+3b)
(a,b)zscaled dir 30 (0.86603a-0.5b,0.5a+0.86603b)
(1,2)dotprod(3,4) 11
(a,b)dotprod(3,4) 3a+4b
dir 21 dotprod dir 51 0.86603
(3,4)dotprod((30,40)rotated 90) 0
Chapter 8: Algebraic Expressions 69

(Recall that plain converts ˜z$™ into ˜(x$,y$)™ when $ is any su¬x .) The xpart
operations exhibited here are almost all self-evident. When a point or vector is rotated,
it is moved counterclockwise about (0, 0) through a given number of degrees. - right
computes the rotated coordinates by using sines and cosines in an appropriate slanted
way; you don™t have to remember the formulas! Although you cannot use ˜*™ to multiply dotprod
a pair by a pair, you can use ˜zscaled™ to get the e¬ect of complex number multiplication: z
Since (1 + 2i) times (3 + 4i) is ’5 + 10i, we have (1, 2) zscaled (3, 4) = (’5, 10). There™s rotated
also a multiplication that converts pairs into numbers: (a, b) dotprod (c, d) = ac + bd. cosines
This is the “dot product,” often written ˜(a, b) · (c, d)™ in mathematics texts; it turns zscaled
complex number
out to be equal to a ++ b times c ++ d times the cosine of the angle between the vectors
(a, b) and (c, d). Since cosd 90—¦ = 0, two vectors are perpendicular to each other if and dot product
only if their dot product is zero. perpendicular
There are operations on strings, paths, and the other types too; we shall study
such things carefully in later chapters. For now, it will su¬ce to give a few direction
examples, keeping in mind that the ¬le expr.mf de¬nes s with any subscript to be a length
string, while p with any subscript is a path. Furthermore s1 has been given the value
"abra", while p1 is ˜(0, 0) . . (3, 3)™ and p2 is ˜(0, 0) . . (3, 3) . . cycle ™.
You type And the result is
s2 unknown string s2
s1&"cad"&s1 "abracadabra"
length s1 4
length p1 1
length p2 2
cycle p1 false
cycle p2 true
substring (0,2) of s1 "ab"
substring (2,infinity) of s1 "ra"
point 0 of p1 (0,0)
point 1 of p1 (3,3)
point .5 of p1 (1.5,1.5)
point infinity of p1 (3,3)
point .5 of p2 (3,0)
point 1.5 of p2 (0,3)
point 2 of p2 (0,0)
point 2+epsilon of p2 (0.00009,-0.00009)
point -epsilon of p2 (-0.00009,0.00009)
point -1 of p1 (0,0)
direction 0 of p1 (1,1)
direction 0 of p2 (4,-4)
direction 1 of p2 (-4,4)
The length of a path is the number of ˜. .™ steps that it contains; the construction
˜cycle path ™ can be used to tell whether or not a particular path is cyclic. If you say
70 Chapter 8: Algebraic Expressions

just ˜p1™ you get to see path p1 with its control points: control points
(0,0)..controls (1,1) and (2,2)

Similarly, ˜p2™ is
(0,0)..controls (2,-2) and (5,1)
..(3,3)..controls (1,5) and (-2,2)

and ˜subpath (0,1) of p2™ is analogous to a substring:
(0,0)..controls (2,-2) and (5,1)

The expression ˜point t of p2 ™ gives the position of a point that moves along path p2 ,
starting with the initial point (0, 0) at t = 0, then reaching point (3, 3) at t = 1,
etc.; the value at t = 1/2 is the third-order midpoint obtained by the construction of
Chapter 3, using intermediate control points (2, ’2) and (5, 1). Since p2 is a cyclic
path of length 2, point (t + 2) of p2 is the same as point t. Path p1 is not cyclic, so its
points turn out to be identical to point 0 when t < 0, and identical to point 1 when
t > 1. The expression ˜direction t of path ™ is similar to ˜point t of path ™; it yields a
vector for the direction of travel at time t.

Paths are not necessarily traversed
at constant speed. For example, the
diagram at the right shows point t of p2 at
twenty equally spaced values of t. -
moves faster in this case at time 1.0
than at time 1.2; but the points are spread (Figure 8a will be inserted here; too bad you
out fairly well, so the concept of fractional can™t see it now.)

time can be useful. The diagram shows, in-
cidentally, that path p2 is not an especially
good approximation to a circle; there is no
left-right symmetry, although the curve from
point 1 to point 2 is a mirror image of the
curve from point 0 to point 1. This lack of
circularity is not surprising, since p2 was de¬ned by simply specifying two points, (0, 0)
and (3, 3); at least four points are needed to get a path that is convincingly round.

The ampersand operation ˜&™ can be used to splice paths together in much the
same way as it concatenates strings. For example, if you type ˜p2 & p1™, you
get the path of length 3 that is obtained by breaking the cyclic connection at the end
of path p2 and attaching p1 :
(0,0)..controls (2,-2) and (5,1)
..(3,3)..controls (1,5) and (-2,2)
..(0,0)..controls (1,1) and (2,2)

Concatenated paths must have identical endpoints at the junction.
Chapter 8: Algebraic Expressions 71

You can even “slow down the clock” by concatenating subpaths that have precedence
non-integer time speci¬cations. For example, here™s what you get if you ask
for ˜subpath (0,.5) of p2 & subpath (.5,2) of p2 & cycle™: tertiary
(0,0)..controls (1,-1) and (2.25,-0.75) ± primary
..(3,0)..controls (3.75,0.75) and (4,2)
..(3,3)..controls (1,5) and (-2,2) ± secondary
..cycle ± tertiary
± expression
When t goes from 0 to 1 in subpath (0, .5) of p2 , you get the same points as when t
goes from 0 to .5 in p2 ; when t goes from 0 to 1 in subpath (.5, 2) of p2 , you get the
same points as when t goes from .5 to 1 in p2 ; but when t goes from 1 to 2 in subpath
(.5, 2) of p2 , it™s the same as the segment from 1 to 2 in p2 .
Let™s conclude this chapter by discussing the exact rules of precedence by
which decides what operations to do ¬rst. The informal notion of
“magnetism” gives a good intuitive picture of what happens, but syntax rules express
things unambiguously in borderline cases.
The four levels of precedence correspond to four kinds of formulas, which
are called primaries, secondaries, tertiaries, and expressions. A primary is
a variable or a constant or a tightly bound unit like ˜2x™ or ˜sqrt 2™; a secondary is a
primary or a sequence of primaries connected by multiplicative operators like ˜*™ or
˜scaled™; a tertiary is a secondary or a sequence of secondaries connected by additive
operators like ˜+™ or ˜++™; an expression is a tertiary or a sequence of tertiaries connected
by external operators like ˜<™ or ˜..™. For example, the expression
is composed of the primaries ˜a™, ˜b™, ˜2™, ˜3c™, and ˜sqrt4d™; the last of these is a primary
containing ˜4d™ as a primary within itself. The subformulas ˜a™, ˜b/2™, and ˜3c*sqrt4d™
are secondaries; the subformulas ˜a+b/2™ and ˜3c*sqrt4d™ are tertiaries.
If an expression is enclosed in parentheses, it becomes a primary that can be
used to build up larger secondaries, tertiaries, etc.
The full syntax for expressions is quite long, but most of it falls into a simple
pattern. If ±, β, and γ are any “types””numeric, boolean, string, etc.”then
± variable refers to a variable of type ±, β primary refers to a primary of type β,
and so on. Almost all of the syntax rules ¬t into the following general framework:
± primary ’’ ± variable | ± constant | ( ± expression )
| operator that takes type β to type ± β primary
± secondary ’’ ± primary
| β secondary multiplicative op taking types β and γ to ± γ primary
± tertiary ’’ ± secondary
| β tertiary additive op taking types β and γ to ± γ secondary
± expression ’’ ± tertiary
| β expression external op taking types β and γ to ± γ tertiary
These schematic rules don™t give the whole story, but they do give the general structure
of the plot.
72 Chapter 8: Algebraic Expressions

Chapter 25 spells out all of the syntax rules for all types of expressions. We numeric primary
shall consider only a portion of the numeric and pair cases here, in order to
have a foretaste of the complete menu: ]
numeric primary ’’ numeric atom length
| numeric atom [ numeric expression , numeric expression ] length
| length string primary xpart
| length path primary ypart
numeric atom
| length pair primary (
| angle pair primary )
| xpart pair primary normaldeviate
numeric token primary
| ypart pair primary /
| numeric operator numeric primary numeric operator
numeric atom ’’ numeric variable sqrt
| numeric token primary cosd
| ( numeric expression ) mlog
| normaldeviate ¬‚oor
numeric token primary ’’ numeric token / numeric token uniformdeviate
| numeric token not followed by ˜/ numeric token ™ scalar multiplication operator
numeric secondary
numeric operator ’’ sqrt | sind | cosd | mlog | mexp times or over
| floor | uniformdeviate | scalar multiplication operator *
scalar multiplication operator ’’ plus or minus numeric tertiary
| numeric token primary not followed by + or - or a numeric token plus or minus
numeric secondary ’’ numeric primary +
| numeric secondary times or over numeric primary Pythagorean plus or minus
times or over ’’ * | / ++
numeric tertiary ’’ numeric secondary numeric expression
| numeric tertiary plus or minus numeric secondary fractions
| numeric tertiary Pythagorean plus or minus numeric secondary mediation
plus or minus ’’ + | - ASCII
Pythagorean plus or minus ’’ ++ | +-+ xxpart
numeric expression ’’ numeric tertiary ceiling
All of the ¬nicky details about fractions and such things are made explicit by this
syntax. For example, we can use the rules to deduce that ˜sind-1/3x-2™ is interpreted
as ˜(sind(-(1/3x)))-2™; notice that the ¬rst minus sign in this formula is considered
to be a “scalar multiplication operator,” which comes in at the primary level, while the
second one denotes subtraction and enters in the construction of numeric tertiary .
The mediation or “of-the-way” operation ˜t[a, b]™ is handled at the primary level.
Several operations that haven™t been discussed yet do not appear in the syntax
above, but they ¬t into the same general pattern; for example, we will see later
that ˜ASCII string primary ™ and ˜xxpart transform primary ™ are additional cases of
the syntax for numeric primary . On the other hand, several operations that we have
discussed in this chapter do not appear in the syntax, because they are not primitives
of itself; they are de¬ned in the plain base (Appendix B). For
example, ˜ceiling™ is analogous to ˜floor™, and ˜**™ is analogous to ˜*™. Chapter 20
explains how allows extensions to its built-in syntax, so that additional
operations can be added at will.
Chapter 8: Algebraic Expressions 73

EXERCISE 8.7 pair primary
How does interpret ˜2 2™ ? (There™s a space between the 2™s.)
According to expr.mf, the value of ˜1/2/3/4™ is 0.66667; the value of ˜a/2/3/4™ )
is 0.375a. Explain why.
The rules of pair expression are similar to those for numeric expression , so
it™s convenient to learn them both at the same time. of
pair secondary
pair primary ’’ pair variable *
| ( numeric expression , numeric expression ) transformer
| ( pair expression ) scaled
| numeric atom [ pair expression , pair expression ] shifted
| point numeric expression of path primary slanted
| scalar multiplication operator pair primary xscaled
pair secondary ’’ pair primary yscaled
| pair secondary times or over numeric primary pair tertiary
| numeric secondary * pair primary pair expression
| pair secondary transformer GRIMM
transformer ’’ rotated numeric primary
| scaled numeric primary
| shifted pair primary
| slanted numeric primary
| transformed transform primary
| xscaled numeric primary
| yscaled numeric primary
| zscaled pair primary
pair tertiary ’’ pair secondary
| pair tertiary plus or minus pair secondary
pair expression ’’ pair tertiary

Try to guess the syntax rules for string primary , string secondary , string
tertiary , and string expression , based solely on the examples that have appeared in
this chapter. [Hint: The ˜&™ operation has the same precedence as ˜..™.]

A maiden was sitting there who was lovely as any picture,
nay, so beautiful that no words can express it.
” JAKOB and WILHELM GRIMM, Fairy Tales (1815)

He looked astonished at the expression.
” EMILY BRONTE, Wuthering Heights (1847)
(page 74)

Chapter 9: Equations 75

The variables in a program receive their values by appearing in equations
equations, which express relationships that the programmer wants to achieve. smoke
We™ve seen in the previous chapter that algebraic expressions provide a rich mode setup
language for dealing with both numerical and graphical relationships. Thus it is
possible to express a great variety of design objectives in precise form by stating
that certain algebraic expressions should be equal to each other.
The most important things a programmer needs to know
about equations are (1) how to translate intuitive design concepts into formal
equations, and (2) how to translate formal equations into intuitive design con-
cepts. In other words, it™s important to be able to write equations, and it™s
also important to be able to read equations that you or somebody else has writ-
ten. This is not nearly as di¬cult as it might seem at ¬rst. The best way to
learn (1) is to get a lot of practice with (2) and to generalize from speci¬c ex-
amples. Therefore we shall begin this chapter by translating a lot of equations
into “simple English.”
Equation Translation
a = 3.14 The value of a should be 3.14.
3.14 = a The number 3.14 should be the value of a. (This
means the same thing as ˜a = 3.14™; the left and
right sides of an equation can be interchanged
without a¬ecting the meaning of that equation
in any way.)
mode = smoke The value of mode should be equal to the value
of smoke . (Plain assigns a special
meaning to ˜smoke ™, so that if mode setup is
invoked when mode = smoke the computer will
prepare “smoke proofs” as explained in Chapter 5
and Appendix H.)
y3 = 0 The y coordinate of point 3 should be zero; i.e.,
point 3 should be at the baseline. (Point 3 is
also known as z3 , which is an abbreviation for
the pair of coordinates (x3 , y3 ), if you are using
the conventions of plain .)
x9 = 0 The x coordinate of point 9 should be zero; i.e.,
point 9 should be at the left edge of the type box
that encloses the current character.
x1l = curve sidebar The x coordinate of point 1l should be equal to
the value of the variable called curve sidebar .
This puts z1l a certain distance from the left
edge of the type.
76 Chapter 9: Equations

x1 = x2 Points 1 and 2 should have the same x coordi- mode setup
nate; i.e., they should have the same horizontal beginchar
position, so that one will lie directly above or w
below the other. bounding box
y 4 = y5 + 1 Point 4 should be one pixel higher than point 5. distance
(However, points 4 and 5 might be far apart; this
equation says nothing about the relation between
x4 and x5 .)

y6 = y7 + 2mm Point 6 should be two millimeters higher than
point 7. (Plain ™s mode setup rou-
tine sets variable mm to the number of pixels in
a millimeter, based on the resolution determined
by mode and mag .)

x4 = w ’ .01in Point 4 should be one-hundredth of an inch inside
the right edge of the type. (Plain ™s
beginchar routine sets variable w equal to the
width of whatever character is currently being
drawn, expressed in pixels.)

y4 = .5h Point 4 should be halfway between the baseline
and the top of the type. (Plain ™s
beginchar sets h to the height of the current
character, in pixels.)

y6 = ’d Point 6 should be below the baseline, at the bot-
tom edge of the type. (Each character has a
“bounding box” that runs from (0, h) at the up-
per left and (w, h) at the upper right to (0, ’d)
and (w, ’d) at the lower left and lower right; vari-
able d represents the depth of the type. The val-
ues of w, h, and d might change from character
to character, since the individual pieces of type
in a computer-produced font need not have the
same size.)

y8 = .5[h, ’d] Point 8 should be halfway between the top and
bottom edges of the type.

w ’ x5 = 2 x6 The distance from point 5 to the right edge of the
type should be two-thirds of the distance from
point 6 to the left edge of the type. (Since w
is at the right edge, w ’ x5 is the distance from
point 5 to the right edge.)
Chapter 9: Equations 77

z0 = (0, 0) Point 0 should be at the reference point of the reference point
current character, i.e., it should be on the base- top
line at the left edge of the type. This equation is vector
an abbreviation for two equations, ˜x0 = 0™ and
˜y0 = 0™, because an equation between pairs of
coordinates implies that the x and y coordinates
must both agree. (Incidentally, plain -
de¬nes a variable called origin whose value
is (0, 0); hence this equation could also have been
written ˜z0 = origin ™.)
z9 = (w, h) Point 9 should be at the upper right corner of the
current character™s bounding box.
top z8 = (.5w, h) If the pen that has currently been “picked up”
is placed at point 8, its top edge should be at
the top edge of the type. Furthermore, x8 should
be .5w; i.e., point 8 should be centered between
the left and right edges of the type. (Chapter 4
contains further examples of ˜top ™, as well as the
corresponding operations ˜bot ™, ˜lft ™, and ˜rt ™.)
z4 = 3 [z5 , z6 ] Point 4 should be three-sevenths of the way from
point 5 to point 6.
z12 ’ z11 = z14 ’ z13 The vector that moves from point 11 to point 12
should be the same as the vector that moves from
point 13 to point 14. In other words, point 12
should have the same direction and distance from
point 11 as point 14 has from point 13.
z3 ’ z2 = Points 3 and 4 should be at the same distance
(z4 ’ z2 ) rotated 15 from point 2, but the direction to point 3 should
be 15 degrees counterclockwise from the direction
to point 4.
(a) x7 ’ 9 = x1 ;
Translate the following equations into “simple English”:
(b) z7 = (x4 , .5[y4 , y5 ]); (c) lft z21 = rt z20 + 1.
Now see if your knowledge of equation reading gives you the ability to write
equations that correspond to the following objectives: (a) Point 13 should be just
as far below the baseline as point 11 is above the baseline. (b) Point 10 should
be one millimeter to the right of, and one pixel below, point 12. (c) Point 43
should be one-third of the way from the top left corner of the type to the bottom
right corner of the type.
78 Chapter 9: Equations

Let™s return now to the six example points (z1 , z2 , z3 , z4 , z5 , z6 ) that were =
used so often in Chapters 2 and 3. Changing the notation slightly, we might say
that the points are
(x1 , y1 ) = (0, h); (x2 , y2 ) = (.5w, h); (x3 , y3 ) = (w, h);
(x4 , y4 ) = (0, 0); (x5 , y5 ) = (.5w, 0); (x6 , y6 ) = (w, 0).
There are many ways to specify these points by writing a series of equations.
For example, the six equations just given would do ¬ne; or the short names z1
through z6 could be used instead of the long names (x1 , y1 ) through (x6 , y6 ).
But there are several other ways to specify those points and at the same time
to “explain” the relations they have to each other. One way is to de¬ne the x
and y coordinates separately:
x1 = x4 = 0; x2 = x5 = .5w; x3 = x6 = w;
y1 = y2 = y3 = h; y4 = y5 = y6 = 0.
allows you to state several equations at once, by using more than
one equality sign; for example, ˜y1 = y2 = y3 = h™ stands for three equations,
˜y1 = y2 ™, ˜y2 = y3 ™, and ˜y3 = h™.
In order to de¬ne the coordinates of six points, it™s necessary to write
twelve equations, because each equation contributes to the de¬nition of one value,
and because six points have twelve coordinates in all. However, an equation
between pairs of coordinates counts as two equations between single numbers;
that™s why we were able to get by with only six ˜=™ signs in the ¬rst set of
equations, while twelve were used in the second.
Let™s look at yet another way to specify those six points, by giving
equations for their positions relative to each other:
z1 ’ z 4 = z 2 ’ z 5 = z 3 ’ z 6
z2 ’ z 1 = z3 ’ z 2 = z5 ’ z 4 = z6 ’ z 5
z4 = origin ; z3 = (w, h).
First we say that the vectors from z4 to z1 , from z5 to z2 , and from z6 to z3 , are
equal to each other; then we say the same thing for the vectors from z1 to z2 ,
z2 to z3 , z4 to z5 , and z5 to z6 . Finally the corner points z4 and z3 are given
explicitly. That™s a total of seven equations between pairs of coordinates, so it
should be more than enough to de¬ne the six points of interest.
However, it turns out that those seven equations are not enough! For
example, the six points
z1 = z4 = (0, 0); z2 = z5 = (.5w, .5h); z3 = z6 = (w, h)
also satisfy the same equations. A closer look explains why: The two formulas
z1 ’ z 4 = z2 ’ z 5 z 2 ’ z 1 = z5 ’ z 4
actually say exactly the same thing. (Add z5 ’ z1 to both sides of the ¬rst
equation and you get ˜z5 ’ z4 = z2 ’ z1 ™.) Similarly, z2 ’ z5 = z3 ’ z6 is the
Chapter 9: Equations 79

same as z3 ’ z2 = z6 ’ z5 . Two of the seven equations give no new information, known
so we really have speci¬ed only ¬ve equations; that isn™t enough. An additional
relation such as ˜z1 = (0, h)™ is needed to make the solution unique.
(For mathematicians.) Find a solution to the seven equations such that
z1 = z2 . Also ¬nd another solution in which z1 = z6 .

At the beginning of a program, variables have no values,
except that plain has assigned special values to variables like smoke
and origin . Furthermore, when you begin a new character with beginchar, any
previous values that may have been assigned to x or y variables are obliterated
and forgotten. Values are gradually established as the computer reads equations
and tries to solve them, together with any other equations that have already
appeared in the program.
It takes ten equations to de¬ne the values of ten variables. If you have
given only nine equations it may turn out that none of the ten variables has yet
been determined; for example, the nine equations
g0 = g1 = g2 = g3 = g4 = g5 = g6 = g7 = g8 = g9
don™t tell us any of the g values. However, the further equation
g 0 + g1 = 1
to deduce that all ten of the g™s are equal to 1 .
will cause 2
always computes the values of as many variables as possible,
based on the equations it has seen so far. For example, after the two equations
a + b + 2c = 3;
a ’ b ’ 2c = 1
the machine will know that a = 2 (because the sum of these two equations is
˜2a = 4™); but all it will know about b and c is that b + 2c = 1.
At any point in a program a variable is said to be either “known” or
“unknown,” depending on whether or not its value can be deduced uniquely
from the equations that have been stated so far. The sample expressions in
Chapter 8 indicate that can compute a variety of things with un-
known variables; but sometimes a quantity must be known before it can be used.
For example, can multiply an unknown numeric or pair variable by
a known numeric value, but it cannot multiply two unknowns.
Equations can be given in any order, except that you might sometimes
need to put certain equations ¬rst in order to make critical values known in the
will ¬nd the solution (a, b, c) = (2, 7, ’3) to
others. For example,
the equations ˜a + b + 2c = 3; a ’ b ’ 2c = 1; b + c = 4™ if you give those equations
in any other order, like ˜b + c = 4; a ’ b ’ 2c = 1; a + b + 2c = 3™. But if the
equations had been ˜a + b + 2c = 3; a ’ b ’ 2c = 1; a — (b + c) = 8™, you would not
have been able to give the last one ¬rst, because would have refused
80 Chapter 9: Equations

to multiply the unknown quantity a by another unknown quantity b + c. Here top
are the main things that can do with unknown quantities: lft
’ unknown comparison
unknown + unknown
unknown ’ unknown hash hash
unknown — known
known — unknown
unknown / known
known [ unknown , unknown ]
unknown [ known , known ]
Some of the operations of plain , de¬ned in Appendix B, also work
with unknown quantities. For example, it™s possible to say top unknown ,
bot unknown , lft unknown , rt unknown , and even
penpos su¬x ( unknown , known ).
program can say ˜ unknown [a, b]™ when a ’ b is known, and
variable a can be compared to variable b in boolean expressions like ˜a < b™
when a ’ b is known. The quantity a ’ b might be known even when a and b aren™t
known by themselves.
You might wonder how is able to keep its knowledge up-to-date,
based on scraps of partial information that it receives from miscellaneous
equations. The best way to understand this is to watch how it happens, by asking the
computer to show certain calculations that it usually keeps to itself. Here™s one way to
do it: Run and say
in response to the opening ˜**™. (Be sure to type the backslash ˜\™, and to use ˜:=™
instead of ˜=™. We will see in Chapter 27 that can be asked to “trace”
many aspects of what it™s doing.) Now type
the machine will reply by saying
## c=-0.5b-0.5a+1.5
since that is how it has digested your equation. (The ˜##™ in this line identi¬es diag-
nostic information that comes from tracingequations .) Now type
will read this as if you had said ˜a-b-2(-0.5b-0.5a+1.5)=1™, since it has
previously learned how to replace c by an expression that involves only a and b. This
new equation can be simpli¬ed by multiplying out the left-hand side and collecting
terms. The result is ˜2a-3=1™, hence will respond with
## a=2
Chapter 9: Equations 81

and it will be your turn to type something again. Say showdependencies
hash hash hash hash
™s response will be
indicating that there is only one variable whose value depends on others, and that its
equation of dependency is now ˜c = ’0.5b + 0.5™. (The previous dependency equation
˜c = ’0.5b ’ 0.5a + 1.5™ has been simpli¬ed to take account of the newly discovered
value, a = 2.) Finally type
this spurs the computer on to say
## b=7
#### c=-3
A line that begins with ˜##™ states what has deduced from the equation
it has just read; a line that begins with ˜####™ states an indirect consequence of that
direct result, if some previously dependent variable has now become known.
It™s interesting to continue the computer experiment just begun by typing the
following lines, one at a time, and watching what happens:
Notice that on the sixth line ( ˜z1 ’ z4 = · · · ™ ) reports four equations, but
on the next line ( ˜z2 ’ z1 = · · · ™ ) it reports only two. This happens because most of
that line is redundant, as we have already observed.
This computer session indicates that deals with two kinds of un-
known numeric variables: dependent variables and independent ones. Every
variable is independent at the beginning of its life, but every equation causes one
of the independent variables to become dependent or known. Each ˜##™ line emit-
ted by tracingequations shows a newly dependent-or-known variable, together with an
equivalent expression that involves only independent variables. For example, the line
˜## c=-0.5b-0.5a+1.5™ means that variable c has just become dependent and that it
equals ’ 1 b ’ 1 a + 1.5, where variables b and a are independent. Similarly, ˜## a=2™
2 2
means that a has just changed from independent to known. When an independent
82 Chapter 9: Equations

variable v changes to dependent or known, the equivalents of all dependent variables redundant
are updated so that they no longer depend on v; in this updating process some or all of
o¬ by x
them may change from dependent to known, whereupon a ˜####™ line will be printed. division
linear dependencies
When reads a numeric equation it replaces all known variables
by their numeric values and all dependent variables by their equivalents. The
resulting equation can be converted into the form
c1 v1 + · · · + cm vm = ±
where the c™s are nonzero constants and the v™s are independent variables; ± is a numeric
constant that might be zero. If some ck is so small that it probably would have been
zero in a calculation free of rounding errors, it is replaced by zero and the corresponding
vk is removed from the equation. Now if m = 0, the equation is considered to be either
redundant (if ± is zero or extremely small) or inconsistent (otherwise). But if m > 0,
chooses an independent variable vk for which ck is maximum, and rewrites
the equation in the form
## vk = (± ’ c1 v1 ’ · · · ’ ck’1 vk’1 ’ ck+1 vk+1 ’ · · · ’ cm vm )/ck .
Variable vk becomes dependent (if m > 1) or known (if m = 1).
Inconsistent equations are equations that have no solutions. For example,
if you say ˜0 = 1™, will issue an error message saying that the
equation is “o¬ by 1.” A less blatant inconsistency arises if you say, e.g, ˜a = b + 1;
b = c + 1; c = a + 1™; this last equation is o¬ by three, for the former equations imply
that c = b ’ 1 = a ’ 2. The computer will simply ignore an inconsistent equation when
you resume processing after such an error.
Redundant equations are equations that say nothing new. For example, ˜0 = 0™
is redundant, and so is ˜a = b + c™ if you have previously said that c = a ’ b.
stops with an error message if you give it a redundant equation between
two numeric expressions, because this usually indicates an oversight in the program.
However, no error is reported when an equation between pairs leads to one or two
redundant equations between numerics. For example, the equation ˜z3 = (0, h)™ will
not trigger an error message when the program has previously established that x3 = 0
or that y3 = h or both.
Sometimes you might have to work a little bit to put an equation into a form
that can handle. For example, you can™t say
x/y = 2
when y is independent or dependent, because allows division only by known
quantities. The alternative
x = 2y
says the same thing and causes the computer no di¬culties; furthermore it is a correct
equation even when y = 0.
™s ability to remember previous equations is limited to “linear”
dependencies as explained above. A mathematician might want to introduce
the condition x ≥ 0 by giving an equation such as ˜x = abs x™; but is
Chapter 9: Equations 83

incapable of dealing with such a constraint. Similarly, can™t cope with an absolute value
equation like ˜x = ¬‚oor x™, which states that x is an integer. Systems of equations that
hash hash hash
involve the absolute value and/or ¬‚oor operation can be extremely di¬cult to solve, showdependencies
and doesn™t pretend to be a mathematical genius. line, point to be on
The rules given earlier explain how an independent variable can become de-
pendent or known; conversely, it™s possible for a dependent variable to become
independent again, in unusual circumstances. For example, suppose that the equation
a + b + 2c = 3 in our example above had been followed by the equation d = b + c + a/4.
Then there would be two dependent variables,
## c=-0.5b-0.5a+1.5
## d=0.5b-0.25a+1.5
Now suppose that the next statement is ˜numeric a™, meaning that the old value of
variable a should be discarded. can™t simply delete an independent variable
that has things depending on it, so it chooses a dependent variable to take a™s place;
the computer prints out
### 0.5a=-0.5b-c+1.5
meaning that 0.5a will be replaced by ’c ’ 1 b + 3 in all dependencies, before a is
2 2
discarded. Variable c is now independent again; ˜showdependencies™ will reveal that
the only dependent variable is now d, which equals 0.75b + 0.5c + 0.75. (This is
correct, for if the variable a is eliminated from the two given equations we obtain
4d = 3b + 2c + 3.) The variable chosen for independence is one that has the greatest
coe¬cient of dependency with respect to the variable that will disappear.
A designer often wants to stipulate that a certain point lies on a certain
line. This can be done easily by using a special feature of plain
called ˜whatever ™, which stands for an anonymous numeric variable that has a di¬erent
unknown value each time you use it. For example,
z1 = whatever [z2 , z3 ]
states that point 1 appears somewhere on the straight line that passes through points
2 and 3. (The expression t[z2 , z3 ] represents that entire straight line, as t runs through
all values from ’∞ to +∞. We want z1 to be equal to t[z2 , z3 ] for some value of t, but
we don™t care what value it is.) The expression ˜whatever [z2 , z3 ]™ is legal whenever the
di¬erence z2 ’ z3 is known; it™s usually used only when z2 and z3 are both known, i.e.,
when both points have been determined by prior equations.
Here are a few more examples of equations that involve ˜whatever ™, together
with their translations into English. These equations are more fun than the
“tame” ones we considered at the beginning of this chapter, because they show o¬ more
of the computer™s amazing ability to deduce explicit values from implicit statements.
Equation Translation
The angle between points 4 and 5 will be 30—¦
z5 ’ z4 = whatever — dir 30
above the horizon. (This equation can also
be written ˜z4 = z5 + whatever — dir 30™, which
states that point 4 is obtained by starting at
84 Chapter 9: Equations

point 5 and moving by some unspeci¬ed mul- dir
tiple of dir 30.)
z7 ’ z6 = whatever — (z3 ’ z2 ) The line from point 6 to point 7 should be unknown quantities, nonnumeric
parallel to the line from point 2 to point 3.
penpos8 (whatever , 60) The simulated pen angle at point 8 should
be 60 degrees; the breadth of the pen is un-
speci¬ed, so it will be determined by other
If z1 , z2 , z3 , and z4 are known points, how can you tell to compute
the point z that lies on the intersection of the lines z1 . . z2 and z3 . . z4 ?
Given ¬ve points z1 , z2 , z3 , z4 , and z5 , explain how to compute z on the line
z1 . . z2 such that the line z . . z3 is parallel to the line z4 . . z5 .
What equation says that the line between points 11 and 12 is
perpendicular to the line between points 13 and 14?
(For mathematicians.) Given three points z1 , z2 , and z3 , explain how to
compute the distance from z1 to the straight line through z2 and z3 .
(For mathematicians.) Given three points z1 , z2 , z3 , and a length l, explain
how to compute the two points on the line z2 . . z3 that are at distance l from z1 .
(Assume that l is greater than the distance from z1 to the line.)
The applications of whatever that we have seen so far have been in equations
between pairs of numeric values, not in equations between simple numerics. Explain
why an equation like ˜a + 2b = whatever ™ would be useless.
All of the equations so far in this chapter have been between numeric expres-
sions or pair expressions. But actually allows equations between
any of the eight types of quantities. For example, you can write
s1="go"; s1&s1=s2
if s1 and s2 are string variables; this makes s1 = "go" and s2 = "gogo". Moreover, the
subsequent equations
s3=s4; s5=s6; s3=s5; s4=s1&"sh"
will make it possible for the machine to deduce that s6 = "gosh".
But nonnumeric equations are not as versatile as numeric ones, because -
does not perform operations on unknown quantities of other types. For
example, the equation
Chapter 9: Equations 85

cannot be used to de¬ne s7 = "eck", because the concatenation operator & works only concatenation
with strings that are already known.
After the declaration ˜string s[]™ and the equations ˜s1=s2=s3™, the statement
˜show s0™ will produce the result ˜unknown string s0™; but ˜show s1™ will
produce ˜unknown string s2™. Similarly, ˜show s2™ and ˜show s3™ will produce ˜unknown
string s3™ and ˜unknown string s1™, respectively. In general, when several nonnumeric
variables have been equated, they will point to each other in some cyclic order.

Let “X” equal my father™s signature.
” FRED ALLEN, Vogues (1924)

” GEORGE ORWELL, Animal Farm (1945)
(page 86)

Chapter 10: Assignments 87

Variables usually get values by appearing in equations, as described in the pre- :=
ceding chapter. But there™s also another way, in which ˜:=™ is used instead of ˜=™. assignment
For example, the io.mf program in Chapter 5 said declarative versus imperative
imperative versus declarative
stem# := trial_stem * pt#
when it wanted to de¬ne the value of stem#.
The colon-equal operator ˜:=™ means “discard the previous value of the
variable and assign a new one”; we call this an assignment operation. It was
convenient for io.mf to de¬ne stem# with an assignment instead of an equation,
because stem# was getting several di¬erent values within a single font. The
alternative would have been to say
numeric stem#; stem# = trial_stem * pt#
(thereby speci¬cally unde¬ning the previous value of stem# before using it in an
equation); this is more cumbersome.
The variable at the left of ˜:=™ might appear also in the expression on
the right. For example,
code := code + 1
means “increase the value of code by 1.” This assignment would make no sense
as an equation, since ˜code = code + 1™ is inconsistent. The former value of
code is still relevant on the right-hand side when ˜code + 1™ is evaluated in this
example, because old values are not discarded until the last minute; they are
retained until just before a new assignment is made.
Is it possible to achieve the e¬ect of ˜code := code + 1™ by using equations and
numeric declarations but not assignments?

Assignments are permitted only when the quantity at the left of the ˜:=™
is a variable. For example, you can™t say ˜code+1:=code™. More signi¬cantly,
things like ˜(x,y):=(0,0)™ are not permitted, although you can say ˜w:=(0,0)™
if w has been declared to be a variable of type pair. This means that a state-
ment like ˜z1:=z2™ is illegal, because it™s an abbreviation for the inadmissible
construction ˜(x1,y1):=(x2,y2)™; we must remember that z1 is not really a
variable, it™s a pair of variables.
The restriction in the previous paragraph is not terribly signi¬cant, be-
cause assignments play a relatively minor rˆle in
o programs. The
best programming strategy is usually to specify equations instead of assignments,
because equations indicate the relationships between variables in a declarative
manner. A person who makes too many assignments is still locked into the habits
of old-style “imperative” programming languages in which it is necessary to tell
the computer exactly how to do everything; ™s equation mechanism
liberates us from that more complicated style of programming, because it lets
the computer take over the job of solving equations.
88 Chapter 10: Assignments

The use of assignments often imposes a de¬nite order on the statements internal quantities
of a program, because the value of a variable is di¬erent before and after an =
assignment takes place. Equations are simpler than assignments because they assignment
can usually be written down in any order that comes naturally to you. right-hand side
Assignments do have their uses; otherwise wouldn™t bother variables, reinitializing
with ˜:=™ at all. But experienced programmers introduce assign- independent variables
ments sparingly”only when there™s a good reason for doing so”because equa- numeric
tions are generally easier to write and more enlightening to read.
™s internal quantities like tracingequations always have known nu-
meric values, so there™s no way to change them except by giving assignments.
The computer experiment in Chapter 9 began with


this illustrates the fact that multiple assignments are possible, just like multiple equa-
tions. Here is the complete syntax for equations and assignments:

equation ’’ expression = right-hand side
assignment ’’ variable := right-hand side
right-hand side ’’ expression | equation | assignment

Notice that the syntax permits mixtures like ˜a + b = c := d + e™; this is the same as
the assignment ˜c := d + e™ and the equation ˜a + b = c™.

In a mixed equation/assignment like ˜a + b = b := b + 1™, the old value of b
is used to evaluate the expressions. For example, if b equals 3 before that
statement, the result will be the same as ˜a + 3 = b := 3 + 1™; therefore b will be set
to 4 and a will be set to 1.

Suppose that you want variable x3 to become “like new,” completely indepen-
dent of any value that it formerly had; but you don™t want to destroy the values of x1
and x2 . You can™t say ˜numeric x[ ]™, because that would obliterate all the xk ™s. What
can you do instead?

Apply to the short program

string s[ ]; s1 = s2 = s3 = s4 ; s5 = s6 ; s2 := s5 ; showvariable s;

and explain the results you get.

If other variables depend on v when v is assigned a new value, the other
variables do not change to re¬‚ect the new assignment; they still act as if
they depended on the previous (unknown) value of v. For example, if the equations
˜2u = 3v = w™ are followed by the assignment ˜w := 6™, the values of u and v won™t
become known, but will still remember the fact that v = .66667u. (This
is not a new rule; it™s a consequence of the rules already stated. When an independent
variable is discarded, a dependent variable may become independent in its place, as
described in Chapter 9.)
Chapter 10: Assignments 89

Apply to the program
tracingequations := tracingonline := 1;
a = 1; a := a + b; a := a + b; a := a + b;
show a, b;
and explain the results you get.

At ¬rst his assignment had pleased,
but as hour after hour passed
with growing weariness,
he chafed more and more.
” C. E. MULFORD, Hopalong Cassidy (1910)

left part ::= variable :=
left part list ::= left part | left part list left part
assignment statement ::= left part list arithmetic expression |
left part list Boolean expression
” PETER NAUR et al., Report on the Algorithmic language ALGOL 60 (1960)
(page 90)

Chapter 11: Magni¬cation and Resolution 91

A single program can produce fonts of type for many di¬erent kinds resolution
of printing equipment, if the programmer has set things up so that the resolution luxo
can be varied. The “plain ” base ¬le described in Appendix B estab- mode
mode setup
lishes a set of conventions that make such variability quite simple; the purpose pt
of the present chapter is to explain those conventions. mm
For concreteness let™s assume that our computer has two output devices. TeX
One of them, called cheapo , has a resolution of 200 pixels per inch (approximately
8 per millimeter); the other, called luxo , has a resolution of 2000 pixels per inch.
We would like to write programs that are able to produce fonts for
both devices. For example, if the ¬le newface.mf contains a program for a new
typeface, we™d like to generate a low-resolution font by invoking with

\mode=cheapo; input newface

and the same ¬le should also produce a high-resolution font if we start with

\mode=luxo; input newface

instead. Other people with di¬erent printing equipment should also be able to
use newface.mf with their own favorite mode values.
The way to do this with plain is to call mode setup near
the beginning of newface.mf; this routine establishes the values of variables like
pt and mm , which represent the respective numbers of pixels in a point and a
millimeter. For example, when mode = cheapo , the values will be pt = 2.7674
and mm = 7.87402; when mode = luxo , they will be pt = 27.674 and mm =
78.74017. The newface.mf program should be written in terms of such variables,
so that the pixel patterns for characters will be about 10 times narrower and
10 times shorter in cheapo mode than they are in luxo mode. For example, a
line that™s drawn from (0, 0) to (3mm , 0) will produce a line that™s about 23.6
pixels long in cheapo mode, and about 236.2 pixels long in luxo mode; the former
line will appear to be 3 mm long when printed by cheapo , while the latter will
look 3 mm long when printed by luxo .
A further complication occurs when a typeface is being magni¬ed; in
such cases the font does not correspond to its normal size. For example, we might
want to have a set of fonts for cheapo that are twice as big as usual, so that users
can make transparencies for overhead projectors. (Such output could also be
reduced to 50% of its size as printed, on suitable reproduction equipment, thereby
increasing the e¬ective resolution from 200 to 400.) TEX allows entire jobs to
be magni¬ed by a factor of 2 if the user says ˜\magnification=2000™; individual
fonts can also be magni¬ed in a TEX job by saying, e.g., ˜\font\f=newface
scaled 2000™. The standard way to produce a font with two-fold magni¬cation
using the conventions of plain is to say, e.g.,

\mode=cheapo; mag=2; input newface;

this will make pt = 5.5348 and mm = 15.74803.
92 Chapter 11: Magni¬cation and Resolution

The mode setup routine looks to see if mag has a known value; if not, mag
it sets mag = 1. Similarly, if mode is unknown, mode setup sets mode = proof . pc


. 3
( 13)