`, \`, \, \);^^@beginchar@
\enddisplay
here \```
is either a quoted single character like |"O"| or a number that
represents the character's position in the final font. The other three
quantities \
```, \, and \ say how big the ^{bounding box}
is, so that typesetting systems like \TeX\ will be able to use the character.
These three dimensions must be given in device-independent units, i.e.,
in ``^{sharped}'' form.
\exercise What are the height and width of the bounding box described
in the @beginchar@ command on line~9 of |io.mf|, given the parameter
values defined on line~2? Give your answer in terms of printer's points.
\answer The width is |0.8em#|, and an |em#| is 10 true points, so the
box will be exactly $8\pt$ wide in device-independent units. The
height will be $7\pt$. \ (And the depth below the baseline will be $0\pt$.)
Each @beginchar@ operation assigns values to special variables called
$w$, $h$, and~$d$, ^^"w" ^^"h" ^^"d" which represent the respective
width, height, and depth of the current character's bounding box,
^{rounded} to the nearest integer number of pixels. Our example file
uses $w$ and~$h$ to help establish the locations of several pen positions
(see lines 12, 13, and~21 of |io.mf|).
\exercise Continuing the previous exercise, what will be the values of
$w$ and~$h$ if there are exactly 3.6 pixels per point?
\answer $8\times3.6=28.8$ rounds to the value $w=29$; similarly, $h=25$.
\ (And $d=0$.)
There's a quoted phrase |"The| |letter| |O"| at the end of line~9; this is
simply a title that will be used in printouts.
The `|endchar|' ^^@endchar@ on line 16 finishes the character that was
begun on line~9, by writing it to an output file and possibly displaying
it on your screen. We will want
to see the positions of the control points $z_1$, $z_2$,
$z_3$, and~$z_4$ that are used in its design, together with the auxiliary
points $(z_{1l},z_{2l},z_{3l},z_{4l})$ and $(z_{1r},z_{2r},z_{3r},z_{4r})$
that come with the "penpos" conventions; the statement `|penlabels(1,2,3,4)|'
^^"penlabels" takes care of labeling these points on the proofsheets.
So much for the letter O. Lines 17--23 are analogous to what we've seen
before, except that there's a new wrinkle: They contain a little program
^^@def@ enclosed by `|def...enddef|', which means that a
{\sl^{subroutine}\/} is being defined. In other words, those lines set up
a whole bunch of \MF\ commands that we will want to execute several times
with minor variations. The subroutine is called "test\_I" and it has three
parameters called "code", "trial\_stem", and "trial\_width" (see line~17).
The idea is that we'll want to draw several different versions of an `I',
having different stem widths and character widths; but we want to type the
program only once. Line~18 defines "stem"\0 and "stem", given a value of
"trial\_stem"; and lines 19--23 complete the program for the letter~I
(copying it from Chapter~4).
\smallskip
Oops---we've been talking much too long about |io.mf|. It's time to stop
rambling and to begin Experiment~2 in earnest, because it will be much
more fun to see what the computer actually does with that file.
Are you brave enough to try Experiment 2? Sure.
Get \MF\ going again, but this time when the machine says `^|**|' you should
say `|io|', since that's the name of the file you have prepared so
laboriously. \ (The file could also be specified by giving its full name
`|io.mf|', but \MF\ automatically adds `|.mf|' ^^|mf| ^^{file names} when
no suffix has been given explicitly.)
If all goes well, the computer should now flash its lights a bit
and---presto---a big `{\manual\IOO}' should be drawn on your screen.
But if your luck is as good as the author's, something will probably go wrong
the first time, most likely because of a typographic error in the file.
A \MF\ program contains lots of data with comparatively little redundancy,
so a single error can make a drastic change in the meaning. Check that
you've typed everything perfectly: Be sure to notice the difference between
the letter~`|l|' and the numeral~`|1|' (especially in line~12, where it
says `|x1l|', not `|x11|' or~`|xll|'); be sure to distinguish between
the letter~`|O|' and the numeral~`|0|' (especially in line~9); be sure to
type the ``underline'' characters in words like `|mode_setup|'. We'll see
later that \MF\ can recover gracefully from most errors, but your job for
now is to make sure that you've got |io.mf| correct.
Once you have a working file, the computer will draw you an `{\manual\IOO}'
and it will also say something like this:
\begintt
(io.mf
The letter O [79])
*
\endtt
What does this mean? Well, `|(io.mf|' means that it has started to read your
file, and `|The| |letter|~|O|' was printed when the title was found in
line~9. Then when \MF\ got to the |endchar| on line~16, it said
`|[79]|' to tell you that it had just output character number~79.
\ (This is the ^{ASCII} code for the letter~|O|; Appendix~C lists all
of these codes, if you need to know them.) The `|)|' after `|[79]|'
means that \MF\ subsequently finished reading the file, and the `^|*|'
means that it wants another instruction.
Hmmm. The file contains programs for both I and O; why did we get only
an~O? Answer: Because lines 17--23 simply define the subroutine "test\_I";
they don't actually {\sl do\/} anything with that subroutine. We need to
activate "test\_I" if we're going to see what it does. So let's type
\begintt
test_I("I",5/6,1/3);
\endtt
this invokes the subroutine, with $"code"=\null$|"I"|,
$"trial\_stem"={5\over6}$, and $"trial\_width"={1\over3}$. The computer will
now draw an~I corresponding to these values,\footnote*{Unless, of course,
there was a typing error in lines 17--23, where "test\_I" is defined.} and
it will prompt us for another command.
It's time to type `^|end|' now, after which \MF\ should tell us that it has
completed this run and made an output file called `|io.2602gf|'. Running this
file through ^|GFtoDVI| as in Experiment~1 will produce two proofsheets,
showing the `{\manual\IOO}' and the `{\manual\IOI}' we have created.
The output won't be shown here, but you can see the results by doing
the experiment personally.
Look at those proofsheets now, because they provide instructive examples
of the simulated broad-edge pen constructions introduced in Chapter~4.
Compare the `{\manual\IOO}' with the program that drew it: Notice that
the $\penpos2$ in line~10 makes the curve slightly thicker at the ^^"penpos"
bottom than at the top; that the equation `$x_{1l}=w-x_{3l}="curve\_sidebar"$'
in line~12 makes the right edge of the curve as far from the right of the
bounding box as the left edge is from the left; that line~13 places point~1
slightly lower than point~3. The proofsheet for `{\manual\IOI}' should look
very much like the corresponding illustration near the end of Chapter~4,
but it will be somewhat larger.
\danger Your proof copy of the `{\manual\IOO}' should show twelve dots
for key points; but only ten of them will be labeled, because there isn't
room enough to put labels on points 2 and~4. The missing ^{labels} usually
^^{overflow labels} appear in the upper right corner, where it might say, e.g.,
`|4|~|=|~|4l|~|+|~|(-1,-5.9)|'; this
means that point $z_4$ is one pixel to the left and 5.9 pixels down
from point~$z_{4l}$, which is labeled. \ (Some implementations omit this
information, because there isn't always room for it.)
The proofsheets obtained in Experiment~2 show the key points and the
bounding boxes, but this extra information can interfere with our
perception of the character shape itself. There's a simple way to
get proofs that allow a viewer to criticize the results from an aesthetic
rather than a logical standpoint; the creation of such proofs will be the
goal of our next experiment.
Here's how to do Experiment~3: Start \MF\ as usual, then type
\begintt
\mode=smoke; input io
\endtt
in response to the `^|**|'. This will input file |io.mf| again,
after establishing ``smoke'' mode. \ (As in Experiment~1, the command line
begins with `|\|' so that the computer knows you aren't starting with
the name of a file.) \ Then complete the run exactly ^^{backslash}
as in Experiment~2, by typing `|test_I("I",5/6,1/3);| |end|';
and apply |GFtoDVI| to the resulting file |io.2602gf|.
This time the proofsheets will contain the same characters as before, but
they will be darker and without labeled points. The bounding boxes will
be indicated only by small markings at the corners; you can put these
boxes next to each other and tack the results up on the wall, then stand
back to see how the characters will look when set by a high-resolution
typesetter. \ (This way of working is called ^"smoke" mode because it's
analogous to the ``smoke proofs'' that punch-cutters traditionally used to
test their handiwork. They held the newly cut type over a candle flame so
that it would be covered with carbon; then they pressed it on paper to
make a clean impression of the character, in order to see whether changes
were needed.)
\danger Incidentally, many systems allow you to invoke \MF\ by typing
a one-line command like `|mf|~|io|' in the case of Experiment~2; you
don't have to wait for the `|**|' before giving a file name. Similarly,
the one-liners `|mf|~|\relax|' and `|mf|~|\mode=smoke;| |input|~|io|' can be
used on many systems at the beginning of Experiments 1 and~3. You might want
to try this, to see if it works on your computer; or you might ask
somebody if there's a similar shortcut.
Experiments 1, 2, and 3 have demonstrated how to make proof drawings of
test characters, but they don't actually produce new fonts that can be
used in typesetting. For this, we move onward to Experiment~4, in which
we put ourselves in the position of a person who is just starting to
design a new typeface. Let's imagine that we're happy with the~O of
|io.mf|, and that we want a ``sans serif'' I in the general style produced
by "test\_I", but we aren't sure about how thick the stem of the~I
should be in order to make it blend properly with the~O. Moreover, we aren't
sure how much white space to leave at the sides of the~I. So~we want to do
some typesetting experiments, using a sequence of different I's.
The ideal way to do this would be to produce a high-resolution test font and to
view the output at its true size. But this may be too expensive, because fine
printing equipment is usually available only for large production runs.
The next-best alternative is to use a low-resolution printer but to magnify
the output, so that the resolution is effectively increased. We shall adopt
the latter strategy, because it gives us a chance to learn about
^{magnification} as well as fontmaking.
After starting \MF\ again, you can begin Experiment 4 by typing
\begintt
\mode=localfont; mag=4; input io
\endtt
in response to the `|**|'. The ^{plain base} at your installation is supposed
to recognize ^|localfont| as the name of the mode that makes fonts for your
``standard'' output device. The equation `|mag=4|' means that this run will
produce a font that is magnified fourfold; i.e., the results will be
4~times bigger than usual.
The computer will read |io.mf| as before, but this time it won't display an~`O';
characters are normally not displayed in fontmaking modes, because we usually
want the computer to run as fast as possible when it's generating a font
that has already been designed. All you'll see is `|(io.mf| |[79])|',
followed by~`^|*|'. Now the fun starts: You should type
\begintt
code=100;
for s=7 upto 10:
for w=5 upto 8:
test_I(incr code,s/10,w/20);
endfor endfor end.
\endtt
(Here `^|upto|' must be typed as a single word.) \ We'll learn about
repeating things with `^|for||...|^|endfor|' in Chapter~19. This little
program produces 16 versions of the letter~I, with stem widths of
$7\over10$, $8\over10$, $9\over10$, and~${10\over10}\pt$, and with
character widths of $5\over20$, $6\over20$, $7\over20$, and~${8\over20}\,
\rm em$. The sixteen trial characters will appear in positions 101 through~116
of the font; it turns out that these are the ^{ASCII} codes for lowercase
letters |e| through~|t| inclusive. \ (Other codes would have been used if
`|code|' had been started at a value different from~100. The construction
`|incr|~|code|' increases the value of |code| by~1 and produces the new value;
thus, each use of |test_I| has a different code number.) ^^"incr"
This run of \MF\ will not only produce a generic font |io.nnngf|, it will also
create a file called |io.tfm|, the ``^{font metric file}'' that tells
^^{output of METAFONT} ^^|tfm|
typesetting systems like \TeX\ how to make use of the new font. The remaining
part of Experiment~4 will be to put \TeX\ to work: We shall make some test
patterns from the new font, in order to determine which `I' is best.
You may need to ask a local system wizard for help at this point, because
it may be necessary to move the file |io.tfm| to some special place where
\TeX\ and the other typesetting software can find it. Furthermore, you'll
need to run a program that converts |io.nnngf| to the font format used by your
local output device. But with luck, these will both be fairly simple
operations, and a new font called `|io|' will effectively be installed
on your system. This font will contain seventeen letters, namely an |O| and
sixteen |I|'s, where the |I|'s happen to be in the positions normally occupied
by |e|, |f|, \dots,~|t|. Furthermore, the font will be magnified fourfold.
\danger The magnification of the font will be reflected in its file name.
For example, if "localfont" mode is for a device with 200 pixels per inch,
the |io| font at 4$\times$ magnification will be called `|io.800gf|'.
You can use \TeX\ to typeset from this font like any other, but for the
purposes of Experiment~4 it's best to use a special \TeX\ package that has
been specifically designed for font testing. All you need to do is to
run \TeX---which is just like running \MF\!, except that you call it `|tex|'
instead of `|mf|'; and you simply type `^|testfont|' in reply to \TeX's
`|**|'. \ (The |testfont| routine should be available on your system; if
not, you or somebody else can type it in, by copying the relevant material
from Appendix~H\null.) \ You will then be asked for the name of the font
you wish to test. Type
\begintt
io scaled 4000
\endtt
(which means the |io| font magnified by 4, in \TeX's jargon),
since this is what \MF\ just created. The machine will now ask you for
a test command, and you should reply
\begintt
\mixture
\endtt
to get the ``^{mixture}'' test. \ (Don't forget the ^{backslash}.) \
You'll be asked for a ^{background letter}, a starting letter, and an
ending letter; type `|O|', `|e|', and `|t|', respectively. This will
produce sixteen lines of typeset output, in which the first line contains
a mixture of |O| with~|e|, the second contains a mixture of |O|~with~|f|,
and so on. To complete Experiment~4, type `|\end|' to \TeX, and print the
file |testfont.dvi| ^^|dvi| that \TeX\ gives you.
\setbox0=\hbox{\kern.5pt I\kern.5pt} \def\\{\copy0}
If all goes well, you'll have sixteen lines that say `O\\OO\\\\OOO\\\\\\O\\',
but with a different I on each line. In order to choose the line that looks
best, without being influenced by neighboring lines, it's convenient to take
two sheets of blank paper and use them to mask out all of the lines
except the one you're studying. Caution: These letters are four times
larger than the size at which the final font is meant to be viewed,
so you should look at the samples from afar. Xerographic reductions may
introduce distortions that will give misleading results. Sometimes when
you stare at things like this too closely, they all look wrong, or
they all look right; first impressions are usually more significant
than the results of logical reflection. At any rate, you should be able
to come up with an informed judgment about what values to use for the
stem width and the character width of a decent `I'; these can then be
incorporated into the program, the `|def|' and `|enddef|' parts of
|io.mf| can be removed, and you can go on to design other characters
that go with your I and~O. Furthermore you can always go back and make
editorial changes after you see your letters in more contexts.
\ddangerexercise The goddess Io was known in Egypt as ^{Isis}.
Design an `{\manual\IOS}' for her.
\answer Here's one way, using a variable "slab" to control the
\rightfig A5a ({200\apspix} x 252\apspix) ^-71pt
^^{S} pen breadth at the ends of the stroke:
\begintt
slab#:=.8pt#; define_blacker_pixels(slab);
beginchar("S",5/9em#,cap#,0); "The letter S";
penpos1(slab,70); penpos2(.5slab,80);
penpos3(.5[slab,thick],200); penpos5(.5[slab,thick],210);
penpos6(.7slab,80);
penpos7(.25[slab,thick],72);
x1=x5; y1r=.94h+o;
x2=x4=x6=.5w; y2r=h+o; y4=.54h; y6l=-o;
x3r=.04em; y3=.5[y4,y2];
x5l=w-.03em; y5=.5[y4,y6];
.5[x7l,x7]=.04em; y7l=.12h-o;
path trial; trial=z3{down}..z4..{down}z5;
pair dz; dz=direction 1 of trial;
penpos4(thick,angle dz-90);
penstroke z1e..z2e{left}..z3e{down}
..z4e{dz}..z5e{down}..z6e{left}..z7e;
penlabels(1,2,3,4,5,6,7); endchar;
\endtt
Notice that the pen angle at point 4 has been found by letting \MF\
^^{direction} construct a ^{trial path} through the center points,
then using the ^{perpendicular} direction. The letters work reasonably
well at their true size: `{\manual\IOS\IOO} {\manual\IOI\IOO}
{\manual\IOI\IOS} {\manual\IOI\IOS\IOI\IOS}.'
Well, this isn't a book about type design; the example of |io.mf| is
simply intended to illustrate how a type designer might want to operate,
and to provide a run-through of the complete process from design of
type to its use in a document. We must go back now to the world of
computerese, and study a few more practical details about the use of \MF\!.
This has been a long chapter, but take heart: There's only one more
experiment to do, and then you will know enough about \MF\ to run it
fearlessly by yourself forever after. The only thing you are still missing
is some information about how to cope with error messages. Sometimes
\MF\ stops and asks you what to do next. Indeed, this may have already
happened, and you may have panicked.
Error messages can be terrifying when you aren't prepared for them;
but they can be fun when you have the right attitude. Just remember that
you really haven't hurt the computer's feelings, and that nobody will
hold the errors against you. Then you'll find that running \MF\ might
actually be a creative experience instead of something to dread.
The first step in Experiment 5 is to plant some intentional mistakes
in the input file. Make a copy of |io.mf| and call it |badio.mf|; then
change line~1 of |badio.mf| to
\begintt
mode setup; % an intentional error!
\endtt
(thereby omitting the underline character in |mode_setup|).
Also change the first semicolon (\thinspace`|;|'\thinspace) on line~2
to a colon (\thinspace`|:|'\thinspace);
change `|thick,10|' to `|thick,l0|' on line~10 (i.e., replace the numeral~`|1|'
by the letter~`|l|'\thinspace); and change `|thin|' to `|thinn|' on line~11.
These four changes introduce typical typographic errors, and it will be
instructive to see if they lead to any disastrous consequences.
Now start \MF\ up again; but instead of cooperating with the computer, type
`|mumble|' in reply to the~`|**|'. \ (As long as you're going to make
intentional mistakes, you might as well make some dillies.) \
\MF\ will say that it can't find any file called |mumble.mf|,
and it will ask you for another name. Just hit \ this time;
you'll see that you had better give the name of a real file.
So type `|badio|' and wait for \MF\ to find one of the {\sl faux pas\/}
in that messed-up travesty.
Ah yes, the machine will soon stop, after typing something like this:
\begintt
>> mode.setup
! Isolated expression.
;
l.1 mode setup;
% an intentional error!
?
\endtt
\MF\ begins its error messages with `|!|', and it sometimes precedes them
with one or two related mathematical expressions that are displayed on
lines starting with `^|>>|'. Each error message is also followed by lines
of context that show what the computer was reading at the time of the
error. Such context lines occur in pairs; the top line of the pair (e.g.,
`|mode| |setup;|'\thinspace) shows what \MF\ has looked at so far, and
where it came from (`|l.1|', i.e., line number~1); the bottom line (here
`|%|~|an| |intentional| |error!|'\thinspace) shows what \MF\ has yet to
read. In this case there are two pairs of context lines; the top pair
refers to a semicolon that \MF\ has read once but will be reading again,
because it didn't belong with the preceding material.
You don't have to take out pencil and paper in order to write down the
error messages that you get before they disappear from view, since \MF\
always writes a ``^{transcript}'' or ``^{log file}'' that records what
happened during each session. For example, you should now have a file
called |io.log| containing the transcript of Experiment~4, as well as a file
|mfput.log| that contains the transcript of Experiment~1. \ (The old
transcript of Experiment~2 was probably overwritten when you did
Experiment~3, and again when you did Experiment~4, because all three
transcripts were called |io.log|.) \ At the end of Experiment~5 you'll
have a file |badio.log| that will serve as a helpful reminder of
what errors need to be fixed up.
The `^|?|' that appears after the context display means that \MF\ wants
advice about what to do next. If you've never seen an error message before,
or if you've forgotten what sort of response is expected, you can type
`|?|' now (go ahead and try it!); \MF\ will respond as follows:
\begintt
Type to proceed, S to scroll future error messages,
R to run without stopping, Q to run quietly,
I to insert something, E to edit your file,
1 or ... or 9 to ignore the next 1 to 9 tokens of input,
H for help, X to quit.
\endtt
This is your menu of options. You may choose to continue in various ways:
\smallskip\item{1.}
Simply type \. \MF\ will resume its processing, after
attempting to recover from the error as best it can.
\smallbreak\item{2.} Type `|S|'. \MF\ will proceed without
pausing for instructions if further errors arise. Subsequent error messages
will flash by on your terminal, possibly faster than you can read them, and
they will appear in your log file where you can scrutinize them at your
leisure. Thus, `|S|'~is sort of like typing \ to every message.
\smallbreak\item{3.} Type `|R|'. This is like `|S|' but even stronger,
since it tells \MF\ not to stop for any reason, not even if a file name
can't be found.
\smallbreak\item{4.} Type `|Q|'. This is like `|R|' but even more so,
since it tells \MF\ not only to proceed without stopping but also to
suppress all further output to your terminal. It is a fast, but somewhat
reckless, way to proceed (intended for running \MF\ with no operator in
attendance).
\smallbreak\item{5.} Type `|I|', followed by some text that you want to
insert. \MF\ will read this text before encountering what it
would ordinarily see ^^{inserting text online}
^^{online interaction, see interaction} ^^{interacting with MF}
next.
\smallbreak\item{6.} Type a small number (less than 100). \MF\ will
delete this many ^{tokens} from whatever it is
about to read next, and it will pause again to give you another chance to
look things over. ^^{deleting tokens}
\ (A~``token'' is a name, number, or symbol that \MF\ reads as a unit;
e.g., `|mode|' and `|setup|' and `|;|' are the first three tokens
of |badio.mf|, but `|mode_setup|' is the first token of |io.mf|.
Chapter~6 explains this concept precisely.)
\smallbreak\item{7.} Type `|H|'. This is what you should do now and whenever
you are faced with an error message that you haven't seen for a~while. \MF\
has two messages built in for each perceived error: a formal one and an
informal one. The formal message is printed first (e.g., `|!|~|Isolated|
|expression.|'\thinspace); the informal one is printed if you request
more help by typing `|H|', and it also appears in your log file if you
are scrolling error messages. The informal message tries to complement the
formal one by explaining what \MF\ thinks the trouble is, and often
by suggesting a strategy for recouping your losses.^^{help messages}
\smallbreak\item{8.} Type `|X|'. This stands for ``exit.'' It causes \MF\
to stop working on your job, after putting the finishing touches on your
|log| file and on any characters that have already been output to your |gf|
and/or |tfm| files. The current (incomplete) character will not be output.
\smallbreak\item{9.} Type `|E|'. This is like `|X|', but it also prepares
the computer to edit the file that \MF\ is currently reading, at the
current position, so that you can conveniently make a change before
trying again.
\smallbreak\noindent
After you type `|H|' (or `|h|', which also works), you'll get a message
that tries to explain the current problem: The mathematical quantity just
read by \MF\ (i.e., |mode.setup|) was not followed by `|=|' or `|:=|', so
there was nothing for the computer to do with it. Chapter~6 explains that
a ^{space} between tokens (e.g., `|mode|~|setup|'\thinspace) is equivalent to
a ^{period} between tokens (e.g., `|mode.setup|'\thinspace). The correct
spelling `|mode_setup|' would be recognized as a preloaded subroutine of
plain \MF\!, but plain \MF\ doesn't have any built-in meaning for
|mode.setup|. Hence |mode.setup| appears as a sort of orphan, and \MF\
realizes that something is amiss.
In this case, it's OK to go ahead and type \, because we really
don't need to do the operations of @mode\_setup@ when no special mode
has been selected. \MF\ will continue by forgetting the isolated expression,
and it will ignore the rest of line~1 because everything after a
^^{percent} `|%|'~sign is always ignored. \ (This is another thing that
will be explained in Chapter~6; it's a handy way to put ^{comments}
into your \MF\ programs.) \ The changes that were made to line~1 of |badio.mf|
therefore have turned out to be relatively harmless. But \MF\ will
almost immediately encounter the mutilated semicolon in line~2:
\begintt
! Extra tokens will be flushed.
:
l.2 em#:=10pt#:
cap#:=7pt#;
?
\endtt
What does this mean? Type `|H|' to find out. \MF\ has no idea what to
do with a `|:|' at this place in the file, so it plans to recover by
``^{flushing}'' or getting rid of everything it sees, until coming to a
semicolon. It would be a bad idea to type \ now, since you'd lose
the important assignment `|cap#:=7pt#|', and that would lead to worse errors.
You might type `|X|' or `|E|' at this point, to exit from \MF\ and to fix
the errors in lines 1 and~2 before trying again. But it's usually best
to keep going, trying to detect and correct as many mistakes as possible
in each run, since that increases your productivity while
decreasing your computer bills. An experienced \MF\ user will quit
after an error only if the error is unfixable, or if there's almost no
chance that additional errors are present.
The solution in this case is to proceed in two steps: First type `|1|',
which tells \MF\ to delete the next token (the unwanted `|:|'); then type
`|I;|', which inserts a semicolon. This semicolon protects the rest of line~2
from being flushed away,
so all will go well until \MF\ reaches another garbled line.
The next error message is more elaborate, because it is detected while
\MF\ is trying to carry out a "penpos" command; "penpos" is not a
primitive operation (it is defined in plain \MF), hence a lot more
context is given:
\begintt
>> l0
! Improper transformation argument.
;
penpos->...(EXPR3),0)rotated(EXPR4);
x(SUFFIX2)=0.5(x(SUFF...
l.10 penpos1(thick,l0)
; penpos2(.1[thin,thick],90-10);
?
\endtt
At first, such error messages will appear to be complete nonsense to you,
because much of what you see is low-level \MF\ code that you never wrote. But
you can overcome this hangup by getting a feeling for the way \MF\ operates.
The bottom line shows how much progress \MF\ has made so far in the |badio|
file: It has read `|penpos1(thick,l0)|' but not yet the semicolon, on line~10.
The "penpos" routine expands into a long list of tokens; indeed, this list
is so long that it can't all be shown on two lines, and the appearances of
`^|...|' indicate that the definition of "penpos" has been truncated here.
Parameter values are often inserted into the expansion of a high-level
routine; in this case, for example, `|(EXPR3)|' and `|(EXPR4)|' correspond
to the respective parameters `|thick|' and `|l0|', and `|(SUFFIX2)|'
corresponds to~`|1|'. ^^|EXPR| ^^|SUFFIX|
\MF\ detected an error just after encountering the phrase `|rotated(EXPR4)|';
the value of |(EXPR4)| was an undefined quantity (namely `|l0|',
which \MF\ treats as the subscripted variable~`$l_0$'\thinspace), and
^{rotation} is permitted only when a known numeric value has been supplied.
Rotations are particular instances of what \MF\ calls {\sl^{transformations}\/};
hence \MF\ describes this particular error by saying that an ``improper
transformation argument'' was present.
When you get a multiline error message like this, the best clues about the
source of the trouble are usually on the bottom line (since that is what
you typed) and on the top line (since that is what triggered the error
message). Somewhere in there you can usually spot the problem.
If you type `|H|' now, you'll find that
\MF\ has simply decided to continue without doing the requested rotation.
Thus, if you respond by typing \, \MF\ will go on as if the program
had said `|penpos1(thick,0)|'. Comparatively little harm has been done;
but there's actually a way to fix the error perfectly before proceeding:
Insert the correct rotation by typing
\begintt
I rotated 10
\endtt
and \MF\ will rotate by 10 degrees as if `|l0|' had been `|10|'.
What happens next in Experiment 5? \MF\ will hiccup on the remaining
bug that we planted in the file. This time, however, the typo will
not be discovered until much later, because there's nothing wrong
with line~11 as it stands. \ (The variable |thinn| is not defined,
but undefined quantities are no problem unless you're doing something
complicated like rotation. Indeed, \MF\ programs typically
consist of equations in which there are lots of unknowns;
variables get more and more defined as time goes on. Hence spelling
errors cannot possibly be detected until the last minute.) \
Finally comes the moment of truth, when |badio| tries to draw a
path through an unknown point; and you will get an error message
that's even scarier than the previous one:
\begintt
>> 0.08682thinn+144
! Undefined x coordinate has been replaced by 0.
{
...FFIX0){up}..z4(SUFFIX0){
left}..cycle; ENDFOR
penstroke->...ath_.e:=(TEXT0);endfor
.if.cycle.path_.l:cyc...
;
l.15 ... ..z3e{up}..z4e{left}..cycle;
|quad
?
\endtt
Wow; what's this? The expansion of @penstroke@ involves a ``@for@ loop,''
and the error was detected in the midst of it. The
expression `|0.08682thinn+144|' just above the error message implies that
the culprit in this case was a misspelled `|thin|'. If that hadn't been
enough information, you could have gleaned another clue from the fact that
`|z4(SUFFIX0)|' has just been read; |(SUFFIX0)| is the current loop value
and `||' indicates that the value in question is `|l|', hence
$z_{4l}$ is under suspicion. \ (Sure enough, the undefined $x$~coordinate
that provoked this error can be shown to be $x_{4l}=0.08682"thinn"+144$.)
In any event the mistake on line~11 has propagated too far to be fixable,
so you're justified in typing `|X|' or~`|E|' at this point. But type~`|S|'
instead, just for fun: This tells \MF\ to plunge ahead, correcting all
remaining errors as best it can. \ (There will be a few more problems,
since several variables still depend on `|thinn|'.) \ \MF\ will draw a
very strange letter~O before it gets to the end of the file. Then you
should type `|end|' to terminate the run.
If you try to edit |badio.mf| again, you'll notice that line~2 still
contains ^^{editing} a colon instead of a semicolon. The fact that you
told \MF\ to delete the colon and to insert additional material doesn't
mean that your file has changed in any way. However, the transcript file
|badio.log| has a record of all the errors, so it's a handy reference when
you want to correct mistakes. \ (Why not look at
|badio.log| now, and |io.log| too, in order to get familiar with log files?)
\dangerexercise Suppose you were doing Experiment 3 with |badio| instead
of~|io|, so you began by saying `|\mode=smoke|; |input| |badio|'. Then you
would want to recover from the error on line~1 by inserting a correct
@mode\_setup@ command, instead of by simply \ing, because
@mode\_setup@ is what really establishes "smoke" mode. Unfortunately if you
try typing `|I|~|mode_setup|' in response to the ``isolated expression''
error, it doesn't work. What should you type instead?
\answer After an ``isolated expression,'' \MF\ thinks it is at the end of
a statement or command, so it expects to see a semicolon next. You should
type, e.g., `|I;|~|mode_setup|' to keep \MF\ happy.
By doing the five experiments in this chapter you have learned at first hand
(1)~how to produce proofsheets of various kinds, including ``smoke proofs'';
(2)~how to make a new font and test it; (3)~how to keep calm when \MF\
issues stern warnings. Congratulations! You're on the threshold of being able to
do lots more. As you read the following chapters, the best strategy
will be for you to continue making trial runs, using experiments
of your own design.
\exercise However, this has been an extremely long chapter,
so you should go outside now and get some {\sl real\/} exercise.
\answer Yes.
\endchapter
Let us learn how Io's frenzy came---
She telling her disasters manifold.
\author \AE SCHYLUS, ^^{Aeschylus} %
{\sl Prometheus Bound\/} (c.\thinspace470 B.C.) % verse 801
% This is the translation by Morshead
\bigskip
To the student who wishes to use graphical methods as a tool,
it can not be emphasized too strongly that practice in the use of that tool
is as essential as a knowledge of how to use it.
The oft-repeated pedagogical phrase, ``we learn by doing,'' is applicable here.
\author THEODORE ^{RUNNING}, {\sl Graphical Mathematics\/} (1927) % p viii
\eject
\beginchapter Chapter 6. How \MF\\Reads What You\\Type
So far in this book we've seen lots of things that \MF\ can do, but we haven't
discussed what \MF\ can't do. We have looked at many examples of commands that
\MF\ can understand, but we haven't dwelt on the fact that the computer will
find many phrases unintelligible. It's time now to adopt a more systematic
approach and to study the exact rules of \MF's language. Then we'll know what
makes sense to the machine, and we'll also know how to avoid ungrammatical
utterances.
A \MF\ program consists of one or more lines of text, where each line is made
up of letters, numbers, punctuation marks, and other symbols that appear on
a standard computer keyboard. A total of 95 different characters can be
employed, namely a blank space plus the 94 visible symbols of standard ^{ASCII}.
\ (Appendix~C describes the American Standard Code for Information
Interchange, popularly known as ``ASCII,'' under which code numbers 33
through~126 have been assigned to 94 specific symbols. This particular
coding scheme is not important to a \MF\ programmer; the only relevant thing
is that 94 different nonblank symbols can be used.)
\MF\ converts each line of text into a series of {\sl ^{tokens}}, and a
programmer should understand exactly how this conversion takes place.
Tokens are the individual lexical units that govern the computer's
activities. They are the basic building blocks from which meaningful
sequences of instructions can be constructed. We discussed tokens briefly
at the end of the previous chapter; now we shall consider them in detail.
Line~9 of the file |io.mf| in that chapter is a typical example of what
the machine might encounter:
\begintt
beginchar("O",0.8em#,cap#,0); "The letter O";
\endtt
When \MF\ reads these ASCII characters it finds sixteen tokens:
\begindisplay \chardef\"=`\" \openup 2pt
\ttok{beginchar}\quad\ttok{(}\quad\ttok{\"O\"}\quad
\ttok{,}\quad\ttok{0.8}\quad\ttok{em}\quad\ttok{\#}\quad\ttok{,}\cr
\ttok{cap}\quad\ttok{\#}\quad\ttok{,}\quad\ttok{0}\quad
\ttok{)}\quad\ttok{;}\quad\ttok{\"The letter O\"}\quad\ttok{;}\cr
\enddisplay
Two of these, |"O"| and |"The| |letter| |O"|, are called {\sl^{string tokens}\/}
because they represent strings of characters. Two of them, `|0.8|' and `|0|',
are called {\sl^{numeric tokens}\/} because they represent numbers. The
other twelve---`|beginchar|', `|(|', etc.---are called {\sl^{symbolic
tokens}\/}; such tokens can change their meaning while a \MF\ program runs,
but string tokens and numeric tokens always have a predetermined significance.
Notice that clusters of letters like `|beginchar|' are treated as a unit;
the same holds with respect to letters mixed with ^{underline} characters,
as in `|mode_setup|'. Indeed,
the rules we are about to study will explain that clusters of other
characters like `|0.8|' and `|:=|' are also considered to be
indecomposable tokens. \MF\ has a definite way of deciding where one
token stops and another one begins.
It's often convenient to discuss ^{grammatical rules} by formulating them in
a special notation that was introduced about 1960 by John ^{Backus} and
Peter ^{Naur}. Parts of speech are represented by named quantities in
^{angle brackets}, and {\sl^{syntax rules}\/} are used to express the ways
in which those quantities can be built~up from simpler units. For example,
here are three syntax rules that completely describe the possible forms of
numeric tokens:
\def\\#1{\thinspace{\tt#1}\thinspace}
\beginsyntax
\is\\0\alt\\1\alt\\2\alt\\3\alt\\4\alt\\5\alt\\6%
\alt\\7\alt\\8\alt\\9
\is\alt
\is\alt[.]
\alt\\.
\endsyntax
The first rule says that a \ is either `|0|' or `|1|' or
$\cdots$ or `|9|'; thus it must be one of the ten numerals. The next
rule says that a \ is either a \ or a
\ followed by a \; thus it must be a sequence
of one or more digits. Finally, a \ has one of three forms,
exemplified respectively by `|15|', `|.05|', and `|3.14159|'.
Syntax rules explain only the surface structure of a language, not the
underlying meanings of things. For example, the rules above tell us that
`|15|' is a \, but they don't imply that `|15|' has
any connection with the number fifteen. Therefore syntax rules are
generally accompanied by rules of {\sl^{semantics}}, which ascribe
meanings to the strings of symbols that meet the conditions of the syntax.
In the case of numeric tokens, the principles of ordinary decimal notation
define the semantics, except that \MF\ deals only with numbers in a
limited range: A numeric token must be less than 4096, and its value is
always rounded to the nearest multiple of $1\over65536$. Thus, for example,
`|.1|'~does not mean $1\over10$, it means $6554\over65536$ (which is
slightly greater than $1\over10$). It turns out that the tokens
`|.099999|' and `|0.10001|' both have exactly the same meaning as
^^{numeric tokens, rounded values} ^^{numeric tokens, maximum value}
`|.1|', because all three tokens represent the value $6554\over65536$.
\dangerexercise Are the following pairs of numeric tokens equivalent
to each other, when they appear in \MF\ programs?
\ (a)~|0| and |0.00001|; \ (b)~|0.00001| and |0.00002|;
\ (c)~|0.00002| and |0.00003|; \ (d)~|04095.999999| and |10000|?
\answer (a) No, the second token represents $1\over65536$. \ (A token has
the same meaning as~`|0|' ^^{zero} if and only if its decimal value
is strictly less than $2^{-17}=.00000\,76293\,94531\,25$.) \ (b)~Yes; both
tokens represent $1\over65536$, because 1~is the nearest integer to both
$.00001\times65536=.65536$ and $0.00002\times65536=1.31072$. \ (c)~No,
|0.00003| represents $2\over65536$. \ (d)~Yes, they both mean ``^{enormous
number} that needs to be reduced''; \MF\ complains in both
cases and substitutes the largest legal numeric token. \ (Rounding
4095.999999 to the nearest multiple of $1\over65536$ yields 4096,
which is too big.)
\MF\ converts each line of text into a sequence of tokens by repeating
the following rules until no more characters remain on the line:
\smallskip
\hang\textindent{1)}If the next character is a ^{space}, or if it's a ^{period}
(\thinspace`|.|'\thinspace) that isn't ^^{decimal point} followed by a
decimal digit or a period, ignore it and move on.
\hang\textindent{2)}If the next character is a ^{percent sign}
(\thinspace`|%|'\thinspace), ignore it and also ignore everything else
that remains on the current line. \ (Percent signs therefore allow you to
write ^{comments} that are unseen by \MF\!.)
\hang\textindent{3)}If the next character is a ^{decimal digit} or a period
that's followed by a decimal digit, the next token is a numeric token,
consisting of the longest sequence of contiguous characters starting at
the current place that satisfies the syntax for \ above.
\hang\textindent{4)}If the next character is a ^{double-quote mark} (\thinspace
`|"|'\thinspace), the next token is a string token, consisting of all
characters from the current place to the next double-quote, inclusive.
\ (There must be at least one more double-quote remaining on the line,
otherwise \MF\ will complain about an ``^{incomplete string}.'') \ A string
token represents the sequence of characters between the double-quotes.
\hang\textindent{5)}If the next character is a ^{parenthesis} (\thinspace
`|(|' or `|)|'\thinspace), a comma (\thinspace`|,|'\thinspace), or a
semicolon (\thinspace`|;|'\thinspace), the next token is a symbolic token
consisting of that single character.
\hang\textindent{6)}Otherwise the next token is a symbolic token consisting
of the next character together with all immediately following characters
that appear in the same row of the following
^^{table of character classes} table:
\begindisplay \displayindent=0pt
|ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz|\hidewidth\cr
|<=>:|\|\cr
|`'|\cr
|+-|\cr
|/*\|\cr
|!?|\cr
|#&@$|\cr
|^~|\cr
|[|\cr
|]|\cr
|{}|\cr
|.|&(see rules 1, 3, 6)\cr
|, ; ( )|&(see rule 5; these characters are ``loners'')\cr
|"|&(see rule 4 for details about string tokens)\cr
|0123456789|&(see rule 3 for details about numeric tokens)\cr
|%|&(see rule 2 for details about comments)\cr
\enddisplay
\noindent
The best way to learn the six rules about tokens is to work the following
exercise, after which you'll be able to read any input file just as the
computer does.
\exercise What tokens does \MF\ find in the (ridiculous) line
\begindisplay
|xx3.1.6..[[a+-bc_d.e] ]"a %" <|\||>(($1. 5"+-""" % weird?|
\enddisplay
\answer \cstok{xx}, \cstok{3.1} (a numeric token), \cstok{.6} (another
numeric token), \cstok{..}, \cstok{[[}, \cstok{a}, \cstok{+-},
\cstok{bc\_d}, \cstok{e}, \cstok{]}, \cstok{]}, {\chardef\"=`\"\cstok{\"a
\%\"} (a string token), \cstok{<\|>}, \cstok{(} (see rule~5), \cstok{(},
\cstok{\$}, \cstok{1} (a numeric token), \cstok{5} (likewise numeric),
\cstok{\"+-\"} (a string token), and \cstok{\"\"}} (a string token that
denotes an empty sequence of characters).
All of these tokens are symbolic unless otherwise mentioned. \ (Notice that
four of the spaces and two of the periods were deleted by rule~1.
One way to verify that \MF\ finds precisely these tokens is to prepare a
test file that says `|isolated| |expression;|' on its first line and that
contains the stated text on its second line. Then respond to \MF's
error message by repeatedly typing `|1|', so that one token is deleted
at a time.)
\exercise Criticize the following statement: \MF\ ignores all spaces in the
input.
\answer The statement is basically true but potentially misleading. You can
insert any number of spaces {\sl between\/} tokens without changing the
meaning of a program, but you cannot insert a space in the {\sl middle\/}
of any token without changing something. You can delete spaces between
tokens {\sl unless\/} that would ``glue'' two adjacent tokens together.
\dangerexercise True or false: If the syntax for \ were
changed to include a fourth alternative, `\|.|', the meaning
of \MF\ programs would not change in any way.
\answer False. It may seem that this new sort of numeric token would be
recognized only in cases where the period is not followed by a digit,
hence the period would be dropped anyway by rule~1. However, the new rule
would have disastrous consequences in a line like `|draw| |z1..z2|'!
\endchapter
Yet wee with all our seeking could see no tokens.
% of any such Wall.
\author PHILEMON ^{HOLLAND}, {\sl ^{Camden}'s Brittania\/} (1610)
% OED says page 518, but I couldn't find it there in the 1637 edition
\bigskip
Unpropitious tokens interfered.
\author WILLIAM ^{COWPER}, {\sl ^{Homer}'s Iliad\/} (1791) % Book 4 verse 455
\eject
\beginchapter Chapter 7. Variables
One of \MF's most important concepts is the notion of a
{\sl^{variable}\/}---something that can take on a variety of different
values. Indeed, this is one of the most important concepts in all of
mathematics, and variables play a prominent r\^ole in almost all
computer languages. The basic idea is that a program manipulates data,
and the data values are stored in little compartments of a computer's
memory. Each little compartment is a variable, and we refer to an item
of data by giving its compartment a name.
For example, the |io.mf| program for the letter {\manual\IOO} in Chapter~5
contains lots of variables. Some of these, like `|x1l|' and `|y1|', represent
coordinates. Others, like `|up|', represent
directions. The variables `|em#|' and `|thin#|' stand for physical,
machine-independent distances; the analogous variables `|em|' and `|thin|'
stand for the corresponding machine-dependent distances in units of pixels.
These examples indicate that different variables are often related to each
other. There's an implicit connection between `|em#|' and `|em|',
between `|x1|' and `|y1|'; the `"penpos"' convention
sets up relationships between `|x1l|', `|x1|', and `|x1r|'. By choosing
the names of variables carefully, programmers can make their programs
much easier to understand, because the relationships between variables
can be made to correspond to the ^^{data structure} structure
of their names.
In the previous chapter we discussed tokens, the atomic elements from which
all \MF\ programs are made. We learned that there are three kinds of
tokens: numeric (representing numbers), string (representing text), and
symbolic (representing everything else). Symbolic tokens have no
intrinsic meaning; any symbolic token can stand for whatever a programmer
wants it to represent.
Some symbolic tokens do, however, have predefined {\sl^{primitive}\/}
meanings, when \MF\ begins its operations. For example, `|+|' stands
initially for ``plus,'' and `|;|' stands for ``finish the current
statement and move on to the next part of the program.'' It is customary
to let such tokens retain their primitive meanings, but any symbolic token
can actually be assigned a new meaning as a program is performed. For
example, the definition of `|test_I|' in |io.mf| makes that token stand
for a {\sl^{macro}}, i.e., a subroutine. We'll see later that you can
instruct \MF\ to `|let| |plus=+|', after which `|plus|' will act just
like `|+|' did.
\MF\ divides symbolic tokens into two categories, depending on their
current meaning. If the symbolic token currently stands for one of \MF's
primitive operations, or if it has been defined to be a macro, it is
called a {\sl^{spark}\/}; otherwise it is called a {\sl^{tag}}. Almost
all symbolic tokens are tags, because only a few are defined to be sparks;
however, \MF\ programs typically involve lots of sparks, because sparks
are what make things happen. The symbolic tokens on the first five lines
of |io.mf| include the following sparks:
\begintt
mode_setup ; := / define_pixels ( , )
\endtt
and the following tags:
\begintt
em # pt cap thin thick o
\endtt
(some of which appear several times). Tags are used to designate variables,
but sparks cannot be used within a variable's name.
Some variables, like `|em#|', have names that are made from more than one token;
in fact, the variable `|x1l|' is named by three tokens, one of which is
numeric. \MF\ has been designed so that it is easy to make compound names
that correspond to the relations between variables. Conventional programming
languages like ^{Pascal} would refer to `|x1l|' by the more
cumbersome notation `|x[1].l|'; it turns out that `|x[1].l|' is an
acceptable way to designate the variable |x1l| in a \MF\ program, but the
shorthand form `|x1l|' is a great convenience because such variables
are used frequently.
Here are the formal rules of syntax by which \MF\ understands the names of
variables:
\def\\#1{\thinspace{\tt#1}\thinspace}
\beginsyntax
\is
\is\alt\alt
\is\alt\\{\char`\[}\\]
\endsyntax
First comes a tag, like `|x|'; then comes a {\sl^{suffix}\/} to the tag,
like `|1l|'.
The suffix might be empty, or it might consist of one or more subscripts
or tags that are tacked on to the original tag. A {\sl^{subscript}\/} is
a numeric index that permits you to construct ^{arrays} of related
variables. The subscript is either a single numeric token, or it is a formula
enclosed in square ^{brackets}; in the latter case the formula should produce a
^^|[| numeric value. For example, `|x[1]|' and `|x[k]|' and `|x[3-2k]|' all mean
^^|]| the same thing as `|x1|', if\/ |k|~is a variable whose value is~1. But
`|x.k|' is not the same; it is the tag~`|x|' suffixed by the tag~`|k|',
not the tag~`|x|' subscripted by the value of variable~|k|.
\danger The variables `|x1|' and `|x01|' and `|x1.00|' are identical.
Since any numeric token can be used as a subscript, fractional indices
are possible; for example, `|x1.5|' is the same as `|x[3/2]|'. Notice,
however, that `|B007|' and `|B.007|' are {\sl not\/} the same variable,
because the latter has a fractional subscript.
\danger \MF\ makes each \ as long as possible. In other words,
a \ is always extended if it is followed by a \
or a~\.
\dangerexercise Explain how to type a reference to the doubly subscripted
variable `|a[1][5]|' without using square brackets.
\answer You can put a space between the subscripts, as in `|a1|~|5|'. \
(We'll see later that a ^{backslash} acts as a null symbol,
hence `|a1\5|' is another solution.)
\dangerexercise Is it possible to refer to {\sl any\/} variable without
using square brackets?
\answer No; |a[-1]| can't be accessed without using |[| and |]|. The
only other form of \ is \, which can't be
negative. \ (Well, strictly speaking, you could say `|let|~|?=[;|
|let|~|??=]|' and then refer to `|a?-1??|'; but that's cheating.)
\ddangerexercise Jonathan H. ^{Quick} (a student) used `|a.plus1|' as the name
of a variable at the beginning of his program; later he said `|let|
|plus=+|'. How could he refer to the variable `|a.plus1|' after that?
\answer Assuming that `|+|' was still a spark when he said `|let|~|plus=+|',
he can't refer to the variable `|a.plus1|' unless he changes the meaning of
|plus| again to make it a~tag. \ (We will eventually learn a way to do this
without permanently clobbering |plus|, as follows: `^|begingroup| ^|save|
|plus;| |a.plus1| ^|endgroup|'.)
\danger \MF\ has several special variables called {\sl^{internal
quantities}\/} that are intimately wired-in to the computer's behavior.
For example, there's an internal quantity called `^|fontmaking|' that controls
whether or not a |tfm| file is produced; another one called `^|tracingtitles|'
governs whether or not titles like |"The| |letter|~|O"| appear on your
terminal; still another one called `^|smoothing|' affects the digitization of
curves. \ (A complete list of \MF's internal quantities appears in
Chapter~25.) \ The name of an internal quantity acts like a tag, but
internal quantities cannot be suffixed or subscripted.
Thus, the syntax rule for \
should actually be replaced by a slightly more complicated pair of rules:
\beginsyntax
\is\alt
\is\alt
\endsyntax
\dangerexercise True or false: Every \ is a legal \.
\answer False. After `|newinternal x;|' you can't say
`|x|\' in a \.
\ddanger The `|[|' and `|]|' that appear in the syntax for \
stand for any symbolic tokens whose current meanings are the same as
\MF's primitive meanings of left and right bracket, respectively;
those tokens don't necessarily have to be brackets. Conversely, if the
meanings of the tokens `|[|' and `|]|' have been changed, brackets cannot
be used to delimit subscripts. Similar remarks apply to all of the
symbolic tokens in all of the syntax rules from now on. \MF\ doesn't look
at the form of a token; it considers only a token's current meaning.
The examples of \MF\ programs in this book have used two different
typographic conventions. Sometimes we refer to variables by using
^{italic type} and/or genuine subscripts, e.g., `"em"' and `$x_{2r}$';
but sometimes we refer to those same variables by using a ^{typewriter}-like
style of type, e.g., `|em|' and~`|x2r|'. In general, the typewriter style
is used when we are mainly concerned with the way a programmer is supposed
to type something that will appear on the terminal or in a file; but fancier
typography is used when we are focusing on the meaning of a program rather
than its ASCII representation. It should be clear how to convert the fancier
form into tokens that \MF\ can actually understand.
\danger In general, we shall use italic type only for tags (e.g., "em",
"x", "r"), while boldface and roman type will be used for sparks
(e.g., @draw@, @fill@, cycle, rotated, sqrt). Tags that consist of special
characters instead of letters will sometimes get special treatment;
for example, |em#| and |z2'| might be rendered $"em"\0$ and $z'_2$,
respectively.
The variables we've discussed so far have almost always had numbers as their
values, but in fact \MF's variables are allowed to assume values of eight
different ^{types}. A variable can be of type
\nobreak\smallskip
\item\bull^{boolean}, representing the values `^{true}' or `^{false}';
\item\bull^{string}, representing sequences of ASCII characters;
\item\bull^{path}, representing a (possibly curved) line;
\item\bull^{pen}, representing the shape of a pen nib;
\item\bull^{picture}, representing an entire pattern of pixels;
\item\bull^{transform}, representing the operations of scaling, rotating,
shifting, reflecting, and/or slanting;
\item\bull^{pair}, representing two numbers (e.g., a point or a vector);
\item\bull^{numeric}, representing a single number.
\smallskip\noindent
If you want a variable to represent something besides a number, you must
first give a {\sl^{type declaration}\/} ^^{declarations} that states
what the type will be. But if you refer to a variable whose type has not
been declared, \MF\ won't complain, unless you try to use it in a way that
demands a value that isn't numeric.
Type declarations are easy. You simply name one of the eight types,
then you list the variables that you wish to declare for that type.
For example, the declaration
\begindisplay
@pair@ "right", "left", $a.p$
\enddisplay
says that "right" and "left" and $a.p$ will be variables of type @pair@,
so that equations like
\begindisplay
$"right"=-"left"=2a.p=(1,0)$
\enddisplay
can be given later. These equations, incidentally, define the values
$"right"=(1,0)$, $"left"=(-1,0)$, and $a.p=(.5,0)$. \ (Plain \MF\
has the stated values of "right" and "left" already built~in.)
The rules for declarations are slightly trickier when subscripts are
involved, because \MF\ insists that all variables whose names are identical
except for subscript values must have the same type. It's possible to
set things up so that, for example, $a$~is numeric, $a.p$ is a pair,
$a.q$ is a pen, $a.r$ is a path, and $a_1$ is a string; but if $a_1$
is a string, then all other variables $a_2$, $a_3$, etc., must also be
strings. In order to enforce this restriction, \MF\ allows only
``collective'' subscripts, represented by empty brackets `^|[]|',
to appear in type declarations. ^^{collective subscripts} For example,
\begintt
path r, r[], x[]arc, f[][]
\endtt
declares $r$ and all variables of the forms $r[i]$, $x[i]"arc"$,
and $f[i][j]$ to be path variables. This declaration doesn't affect
the types or values of other variables like $r[\,]"arc"$; it affects
only the variables that are specifically mentioned.
Declarations destroy all previous values of the variables being defined.
For example, the path declaration above makes $r$ and $r[i]$ and $x[i]"arc"$
and $f[i][j]$ undefined, even if those variables previously had paths
as their values. The idea is that all such variables will start out with a
clean slate so that they can receive appropriate new values based on
subsequent equations. ^^{value, disappearance of}
\exercise Numeric variables don't need to be declared. Therefore is there
ever any reason for saying `|numeric| |x|'\thinspace?
\answer Yes, because it removes any existing value that $x$ may have
had, of whatever type; otherwise you couldn't safely use $x$ in a
numeric equation. It's wise to declare numeric variables when you're
not sure about their former status, and when you're sure that you don't
care what their previous value was. A numeric declaration together with a
comment also provides useful documentation. \ (Incidentally, `|numeric|~|x|'
doesn't affect other variables like `|x2|' or `|x.x|' that might be present.)
\danger The formal syntax rules for type declarations explain these
grammatical conventions precisely. If the symbolic token that begins a
declared variable was previously a spark, it loses its former meaning and
immediately becomes a tag.
\beginsyntax
\is
\is[boolean]\alt[string]\alt[path]\alt[pen]
\alt[picture]\alt[transform]\alt[pair]\alt[numeric]
\is
\alt[,]
\is
\is\alt
\alt\\{\char`\[}\\]
\endsyntax
\dangerexercise Find three errors in the supposed declaration
`|transform| |t42,24t,,t,path|'.
\answer (a)~The `|42|' is illegal because subscripts must be collective.
\ (b)~The `|24|' is illegal because a \ must start with
a \, not a numeric token. \ (c)~There's nothing wrong with
the consecutive commas; the second comma begins a \, so
it loses its former meaning and becomes a tag. Thus \MF\ tries to declare
the variable `|,t,path|'. However, `|path|' cannot appear in a suffix,
since it's a spark. \ (Yes, this is admittedly tricky. Computers follow rules.)
\endchapter
Beings low in the scale of nature are
more variable than those which are higher.
\author CHARLES ^{DARWIN}, {\sl On the Origin of Species\/} (1859) % p149
\bigskip
Among the variables, {\rm Beta ({\cmman\char'14\/}) Persei}, or\/ {\rm^{Algol}},
is perhaps the most interesting, as its period is short.
\author J. NORMAN ^{LOCKYER}, {\sl Elements of Astronomy\/} (1870)
% American edition, p40
\eject
\beginchapter Chapter 8. Algebraic\\Expressions
\MF\ programmers express themselves algebraically by writing algebraic
formulas called {\sl^{expressions}}. The formulas are algebraic in the
sense that they involve variables as well as constants. By combining
variables and constants with appropriate mathematical operations, a
programmer can specify an amazing variety of things with comparative ease.
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., `$x_1$'\thinspace) or a
^{constant} (e.g., `20'\thinspace), or it consists of an ^{operator}
(e.g., `$+$'\thinspace) together with its ^{operands} (e.g.,
`$x_1+20$'\thinspace). The operands are, in turn, expressions built~up in
the same way, perhaps enclosed in ^{parentheses}. For example,
`$(x_1+20)/(x_2-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 find it
difficult to deal with two-dimensional constructions like
\begindisplay
$\displaystyle{x_1+20\over x_2-20}+\sqrt{a^2-{2\over3}\sqrt b}.$
\enddisplay
One-dimensional sequences of tokens are much easier to input and to decode;
hence programming languages generally put such formulas all on one line,
^^{sqrt} by inserting parentheses, brackets, and asterisks as follows:
\begintt
(x[1]+20)/(x[2]-20)+sqrt(a**2-(2/3)*sqrt(b)).
\endtt
\MF\ will understand this formula, but it also accepts a notation that
is shorter and closer to the standard conventions of mathematics:
\begintt
(x1+20)/(x2-20)+sqrt(a**2-2/3sqrt b).
\endtt
We observed in the previous chapter that \MF\ 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 \MF\ programs, hence the language has been set up to facilitate them.
On the other hand, \MF\ 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 suffixed 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; \MF\ deals not only with numeric expressions but also
with boolean expressions, string expressions, and the others. For example,
`$(0,0)\to(x_1,y_1)$'
is a path-valued expression, formed by applying the operator `$\to$' to the
subexpressions `$(0,0)$' and `$(x_1,y_1)$'; these subexpressions, in turn,
have values of type ``pair,'' and they have been built up from values of
type ``numeric.'' Each operation produces a result whose type can be
determined from the types of the operands; furthermore, the simplest
expressions (variables and constants) always have a definite type.
Therefore the machine always knows what type of quantity it is dealing
with, after it has evaluated an expression.
If an expression contains several operators, \MF\ has to decide which
^^{order of operations}
operation should be done first. For example, in the expression `$a-b+c$'
it is important to compute `$a-b$' first, then to add~$c$; if `$b+c$' were
computed first, the result `$a-(b+c)$' would be quite different from the
usual conventions of mathematics. On the other hand, mathematicians
usually expect `$b/c$' to be computed first in an expression like
`$a-b/c$'; multiplications and divisions are usually performed before
additions and subtractions, unless the contrary is specifically indicated
by parentheses as in `$(a-b)/c$'. The general rule is to evaluate
subexpressions in parentheses first, then to do operations in order of
their ``^{precedence}''; if two operations have the same precedence, the
left one is done first. 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 `$\ast$' and `/' are stronger
than the magnets for `$+$' and `$-$', so they stick to their operands more
tightly and we want to perform them first.
\MF\ 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 `$\ast$' and~`/'; then come the additive
operators like `$+$' and~`$-$'. The weakest magnets are operators like
`$\to$' or `$<$'. For example, the expression
\begindisplay
$a+{\rm sqrt}\,b/2x, obtaining the
value~`|>>|~|4|'. Isn't that amazing? Here are some more things to try:
\begindemo
\demohead
1.2-2.3&-1.1\cr
1.3-2.4&-1.09999\cr
1.3*1000&1300.00305\cr
2.4*1000&2399.9939\cr
3/8&0.375\cr
.375*1000&375\cr
1/3&0.33333\cr
1/3*3&0.99998\cr
0.99999&0.99998\cr
1-epsilon&0.99998\cr
1/(1/3)&3.00005\cr
1/3.00005&0.33333\cr
.1*10&1.00006\cr
1+4epsilon&1.00006\cr
\enddemo
These examples illustrate the small errors that occur because \MF\ does
``fixed binary'' ^{arithmetic} using integer multiples of $1\over65536$.
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\over10$ and |2.4| is a little smaller
than~$24\over10$. Small errors get magnified when they are multiplied by
1000, but even after magnification 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\over65536$; \MF\
displays this value as |0.99998| because it is closer to .99998 than to
.99999. Plain \MF\ defines ^"epsilon" to be $1\over65536$, the smallest
representable number that is greater than zero; therefore |1-epsilon|
is $65535\over65536$, and |1+4epsilon| is $65540\over65536$.
\begindemo
\demohead
4096&4095.99998\werror\cr
infinity&4095.99998\cr
1000*1000&32767.99998\werror\cr
infinity+epsilon&4096\cr
100*100&10000\cr
.1(100*100)&1000.06104\cr
(100*100)/3&3333.33333\cr
\enddemo
\MF\ will complain that an `|Enormous| ^^{enormous number} |number| |has|
|been| |reduced|' when you try to introduce constants that are 4096 or~more.
Plain \MF\ defines ^"infinity" 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; \MF\ doesn't
worry about this unless the resulting magnitude is at least 32768.
\dangerexercise If you try `|100*100/3|' instead of `|(100*100)/3|', you
get `|3333.33282|'. Why?
\answer The fraction |100/3| is evaluated first (because such divisions
take precedence); the rounding error in this fraction is then magnified by~100.
\ddanger Sometimes \MF\ 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 undefined
variables 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 {\sl aren't\/} in the book!)
\begindemo
\demohead
b+a&a+b\cr
a+b&a+b\cr
b+a-2b&a-b\cr
2(a-b+.5)&2a-2b+1\cr
.5(b-a)&-0.5a+0.5b\cr
.5[a,b]&0.5a+0.5b\cr
1/3[a,b]&0.66667a+0.33333b\cr
0[a,b]&a\cr
a[2,3]&a+2\cr
t[a,a+1]&t+a\cr
a*b&b\werror\cr
1/b&b\werror\cr
\enddemo
\MF\ 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]$' specifies a number that's halfway
between $a$ and~$b$, as explained in Chapter~2. \MF\ 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 \MF\ works with must be
``^{linear forms},'' i.e., they must be sums of variables with constant
coefficients, plus an optional constant. \ (You might want to try typing
`|t[a,b]|' now, in order to see what error message is given.)
\begindemo
\demohead
sqrt 2&1.41422\cr
sqrt 100&10\cr
sqrt 100*100&1000\cr
sqrt(100*100)&100\cr
sqrt 100(100)&100\cr
sqrt sqrt 100(100)&10\cr
sqrt .01&0.09998\cr
0.09998**2&0.01\cr
2**1/2&1.41422\cr
sqrt 2**2&2\cr
sqrt -1&0\werror\cr
sqrt a&a\werror\cr
\enddemo
Since ^|sqrt| has more ``magnetism'' than |*|, the formula |sqrt|~|100*100|
^^{square roots}
is evaluated as |(sqrt|~|100)*100|; but in `|sqrt|~|100(100)|' the
|100(100)| is computed first. 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 find that \MF's rules of
precedence are fairly natural as you gain experience.
\exercise Is `|sqrt|~|2**2|' computed as `|(sqrt|~|2)**2|' or as
`|sqrt(2**2)|'\thinspace?
\answer A |sqrt| takes precedence over any operation with two operands, hence
the machine computes `|(sqrt|~|2)**2|'; \MF\ was somewhat lucky that the
answer turned out to be exactly~2. \ (The |sqrt| operation computes the
nearest multiple of $1\over65536$, and the rounding error in this quantity
is magnified when it is squared. If you try |sqrt|~|3**2|, you'll get
|3.00002|; also |sqrt|~|2**4| turns out to be |4.00002|.) \ Incidentally,
the ^|**| operation of plain \MF\ has the same precedence as |*| and~|/|;
hence `|x*y**2|' means the same as `|(x*y)**2|', and `|-x**2|' means
`|(-x)**2|', contrary to the conventions of {\eightrm ^{FORTRAN}}.
Some \MF\ expressions have `^{true}' or `^{false}' values, instead of numbers;
we will see later that they can be used to adapt \MF\ programs to special
conditions.
\begindemo
\demohead
0<1&true\cr
0=1&false\cr
a+1>a&true\cr
a>=b&false\werror\cr
"abc"<="b"&true\cr
"B">"a!"&false\cr
"b">"a?"&true\cr
(1,2)<>(0,4)&true\cr
(1,2)<(0,4)&false\cr
(1,a)>(0,b)&true\cr
numeric a&true\cr
known a&false\cr
not pen a&true\cr
known "a" and numeric 1&true\cr
(0>1) or (a1 or a=|', `^|<=|', and `^|<>|' stand respectively for the
^{relations} ^{greater-than-or-equal-to}, ^{less-than-or-equal-to}, and
^{unequal-to}. When strings are compared, \MF\ uses the order of words in
a dictionary, except that it uses ASCII code to define ordering of individual
characters; thus, all uppercase letters are considered to be less than all
lowercase letters. \ (See Appendix~C\null.) \ When pairs of numbers are
compared, \MF\ considers only the $x$~coordinates, unless 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. ^^{pair} ^^{numeric} ^^{pen}
The expression `|known|~|a|' ^^{known} is true if and only if the value
of~|a| is fully known.
\dangerexercise What causes the error messages in `|0>1|~|or|~|a$', ^^|<| ^^|>|
\MF\thinspace\ tries to evaluate this expression by putting things in
parentheses as follows: `$(0>(1\mathbin{\bf or}a))a$' is indeterminate because $a$~is unknown; \MF\ treats this as
false. Finally `${\rm false}.) \ ^^{xpart} ^^{ypart} ^^{shifted} ^^"right" ^^{slanted}
^^{zscaled} ^^{dotprod} ^^"z" The 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. \MF\ computes the rotated coordinates by using
^{sines} and ^{cosines} in an appropriate way; you don't have to
remember the formulas! Although you cannot use `|*|' to multiply
a pair by a pair, you can use `^{zscaled}' to get the effect of
^{complex number} multiplication: Since $(1+2i)$ times $(3+4i)$ is
$-5+10i$, we have $(1,2)\mathbin{\rm zscaled}(3,4)=(-5,10)$.
There's also a ^{multiplication} that converts pairs into numbers:
$(a,b)\mathbin{\rm dotprod}(c,d\mkern1mu)=ac+bd$. This is the
``^{dot product},'' often written `$(a,b)\cdot(c,d\mkern1mu)$' in
mathematics texts; it turns out to be equal to $a\pyth+b$ times
$c\pyth+d$ times the cosine of the angle between the vectors $(a,b)$ and
$(c,d)$. Since cosd$\,90^\circ=0$, two vectors are
^{perpendicular} to each other if and only if their dot ^{product} is zero.
\danger There are operations on strings, paths, and the other types too;
we shall study such things carefully in later chapters. For now, it will
suffice to give a few examples, keeping in mind that the file |expr.mf|
defines |s| with any subscript to be a ^{string}, while |p| with any subscript
is a path. Furthermore $s_1$ has been given the value |"abra"|, while
$p_1$ is `$(0,0)\to(3,3)$' and $p_2$ is `$(0,0)\to(3,3)\to\cycle$'.
\begindemo
\demohead
s2&unknown string s2\cr
s1\&"cad"\&s1&"abracadabra"\cr
length s1&4\cr
length p1&1\cr
length p2&2\cr
cycle p1&false\cr
cycle p2&true\cr
substring (0,2) of s1&"ab"\cr
substring (2,infinity) of s1&"ra"\cr
point 0 of p1&(0,0)\cr
point 1 of p1&(3,3)\cr
point .5 of p1&(1.5,1.5)\cr
point infinity of p1&(3,3)\cr
point .5 of p2&(3,0)\cr
point 1.5 of p2&(0,3)\cr
point 2 of p2&(0,0)\cr
point 2+epsilon of p2&(0.00009,-0.00009)\cr
point -epsilon of p2&(-0.00009,0.00009)\cr
point -1 of p1&(0,0)\cr
direction 0 of p1&(1,1)\cr
direction 0 of p2&(4,-4)\cr
direction 1 of p2&(-4,4)\cr
\enddemo
^^{point} ^^{direction}
The ^{length} of a path is the number of `$\to$' steps that it contains;
the construction `^|cycle|~\' can be used to tell whether or not a
particular path is cyclic. If you say just `|p1|' you get to see
path~$p_1$ with its ^{control points}:
\begintt
(0,0)..controls (1,1) and (2,2)
..(3,3)
\endtt
Similarly, `|p2|' is
\begintt
(0,0)..controls (2,-2) and (5,1)
..(3,3)..controls (1,5) and (-2,2)
..cycle
\endtt
and `|subpath| |(0,1)| |of| |p2|' is analogous to a ^{substring}:^^{subpath}
\begintt
(0,0)..controls (2,-2) and (5,1)
..(3,3)
\endtt
The expression `point $t$ of $p_2$' gives the position of a point that
moves along path~$p_2$, 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 $p_2$ is a cyclic path of length~2,
point $(t+2)$ of~$p_2$ is the same as point~$t$. Path $p_1$ 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~\' is similar to `point~$t$ of \'; it yields a vector for the
direction of travel at time~$t$.
{\ninepoint
\medbreak
\parshape 14 3pc 12pc 3pc 12pc
0pc 15pc 0pc 15pc 0pc 15pc 0pc 15pc 0pc 15pc 0pc 15pc
0pc 15pc 0pc 15pc 0pc 15pc 0pc 15pc 0pc 15pc 0pc 29pc
\noindent
\hbox to0pt{\hskip-3pc\dbend\hfill}%
\rightfig 8a (12pc x 12pc) ^16pt
Paths are not necessarily traversed at constant speed. For example,
the diagram at the right shows point $t$ of~$p_2$ at twenty equally
spaced values of~$t$.
\MF\ moves faster in this case at time~1.0 than at time 1.2; but the
points are spread out fairly well, so the concept of fractional
time can be useful. The diagram shows, incidentally, that
path~$p_2$ 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
$p_2$ was defined by simply specifying two points, $(0,0)$ and~$(3,3)$;
at least four points are needed to get a path that is convincingly round.
\parfillskip=0pt\par}
\ddanger 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~$p_2$ and attaching~$p_1$:
\begintt
(0,0)..controls (2,-2) and (5,1)
..(3,3)..controls (1,5) and (-2,2)
..(0,0)..controls (1,1) and (2,2)
..(3,3)
\endtt
Concatenated paths must have identical endpoints at the junction.
\ddanger You can even ``slow down the clock'' by concatenating subpaths
that have non-integer time specifications. For example, here's what you
get if you ask for `|subpath|~|(0,.5)| |of|~|p2| |&| |subpath| |(.5,2)|
|of|~|p2| |&| |cycle|':
\begintt
(0,0)..controls (1,-1) and (2.25,-0.75)
..(3,0)..controls (3.75,0.75) and (4,2)
..(3,3)..controls (1,5) and (-2,2)
..cycle
\endtt
When $t$ goes from 0 to 1 in subpath $(0,.5)$ of $p_2$, you get the same
points as when $t$ goes from 0 to~.5 in $p_2$; when $t$ goes from 0 to 1
in subpath $(.5,2)$ of~$p_2$, you get the same points as when $t$ goes
from .5 to~1 in~$p_2$; but when $t$ goes from 1 to~2 in subpath
$(.5,2)$ of~$p_2$, it's the same as the segment from 1 to~2 in~$p_2$.
\danger Let's conclude this chapter by discussing the exact rules of
^{precedence} by which \MF\ decides what operations to do first. The
informal notion of ``magnetism'' gives a good intuitive picture of what
happens, but syntax rules express things unambiguously in borderline cases.
\danger The four levels of precedence correspond to four kinds of formulas,
which are called primaries, secondaries, tertiaries, and
expressions. A {\sl^{primary}\/} is a~variable or a constant or a
tightly bound unit like `|2x|' or `|sqrt 2|'; a {\sl^{secondary}\/}
is~a primary or a sequence of primaries connected by multiplicative
operators like `|*|' or `|scaled|'; a {\sl^{tertiary}\/} is a secondary
or a sequence of secondaries connected by additive operators like `|+|'
or `|++|'; an {\sl^{expression}\/} is a tertiary or a sequence of
tertiaries connected by external operators like `|<|' or `|..|'. For example,
the expression
\begintt
a+b/2>3c*sqrt4d
\endtt
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.
\danger If an expression is enclosed in parentheses, it becomes a primary
that can be used to build up larger secondaries, tertiaries, etc.
\danger The full syntax for expressions is quite long, but most of it
falls into a simple pattern. If $\alpha$, $\beta$, and~$\gamma$ are
any ``types''---numeric, boolean, string, etc.---then \<$\alpha$ variable>
refers to a variable of type~$\alpha$, \<$\beta$ primary> refers to a
primary of type~$\beta$, and so on. Almost all of the syntax rules fit into
the following general framework:
\beginsyntax
<$\alpha$ primary>\is<$\alpha$ variable>\alt<$\alpha$ constant>%
\alt[(]<$\alpha$ expression>[)]
\alt<$\beta$ primary>
<$\alpha$ secondary>\is\<$\alpha$ primary>
\alt<$\beta$ secondary><$\gamma$ primary>\kern-1pt
<$\alpha$ tertiary>\is\<$\alpha$ secondary>
\alt<$\beta$ tertiary><$\gamma$ secondary>
<$\alpha$ expression>\is<$\alpha$ tertiary>
\alt<$\beta$ expression><$\gamma$ tertiary>
\endsyntax
These schematic rules don't give the whole story, but they do give the
general structure of the plot.
\danger Chapter 25 spells out all of the syntax rules for all types of
expressions. We shall consider only a portion of the numeric and pair
cases here, in order to have a foretaste of the complete menu:
\def\\#1{\thinspace{\tt#1}\thinspace}
\beginsyntax
\is
\alt[\char'133]%
[,][\char'135]
\alt[length]
\alt[length]
\alt[length]
\alt[angle]
\alt[xpart]
\alt[ypart]
\alt
\is
\alt
\alt[(][)]
\alt[normaldeviate]
\is[/]
\alt
\is[sqrt]\alt[sind]\alt[cosd]\alt[mlog]\alt[mexp]
\alt[floor]\alt[uniformdeviate]\alt
\is
\alt
\is
\alt
\is[*]\alt[/]
\is
\alt
\alt
\is[+]\alt[-]
\is[++]\alt[+-+]
\is
\endsyntax
All of the finicky 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
first 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 \. The
^{mediation} or ``^{of-the-way}'' operation `$t[a,b]$' is handled at the
primary level.
\danger Several operations that haven't been discussed yet do not appear
in the syntax above, but they fit into the same general pattern; for example,
we will see later that `^|ASCII|\' and `^|xxpart|\' are additional cases of the syntax for \.
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 \MF\ itself;
they are defined in the plain \MF\ base (Appendix B\null). For example,
`^|ceiling|' is analogous to `|floor|', and `^|**|' is analogous to~`|*|'.
Chapter~20 explains how \MF\ allows extensions to its built-in syntax,
so that additional operations can be added at will.
\dangerexercise How does \MF\ interpret `|2|~|2|'\thinspace?
\ (There's a space between the 2's.)
\answer It's impossible to make an expression from `\
\', because the rule for \
specifically prohibits this. \MF\ will recognize the first `|2|' as
a \, which is ultimately regarded as a \; the other `|2|' will probably be an extra token that is
flushed away after an error message has been given.
\ddangerexercise 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.
\answer If a numeric token is followed by `|/|\' but
not preceded by `\|/|', the syntax allows it to become part of
an expression only by using the first case of \. Therefore `|1/2/3/4|' must be treated as `|(1/2)/(3/4)|',
and `|a/2/3/4|' must be treated as `|a/(2/3)/4|'.
\danger The rules of \ are similar to those for
\, so it's convenient to learn them both at the same time.
\beginsyntax
\is
\alt[(][,][)]
\alt[(][)]
\alt[\char'133]%
[,][\char'135]
\alt[point][of]
\alt
\is
\alt
\alt[*]
\alt
\is[rotated]
\alt[scaled]
\alt[shifted]
\alt[slanted]
\alt[transformed]
\alt[xscaled]
\alt[yscaled]
\alt[zscaled]
\is
\alt
\is
\endsyntax
\dangerexercise Try to guess the syntax rules for \,
\, $\langle$string tertiary$\rangle$, and \, based solely on the examples that have appeared in this
chapter. \ [{\sl Hint:}\/ The `|&|' operation has the same precedence
as `|..|'.]
\answer \\is\\parbreak
\qquad\alt\\parbreak
\def\\#1{\thinspace{\tt#1}\thinspace}%
\qquad\alt\\(\\\)\parbreak
\qquad\alt\\{substring}\\\{of}\\parbreak
\\is\\parbreak
\\is\\parbreak
\\is\\parbreak
\qquad\alt\\\{\char`\&}\\par
\medskip\noindent
(The full syntax in Chapter~25 includes several more varieties of
\ that haven't been hinted at yet.)
\endchapter
A maiden was sitting there who was lovely as any picture,
% ein bildsch\"one Jungfrau,
nay, so beautiful that no words can express it.
% nein so sch\"on, dass es nicht so sagen ist.
\author JAKOB and WILHELM ^{GRIMM}, {\sl Fairy Tales\/} (1815)
% Kinder- und hausm\"archen, vol 2, #166; translated by Margaret Hunt
% in Strong Hans (Der starke Hans), about 4/5 of the way through
% This quote and the next were found by online computer search at SAIL
% in the files GRIMM[lib,doc] and WUTHER[lib,doc]
\bigskip
He looked astonished at the expression.
% my face assumed... middle of chapter 13
\author EMILY ^{BRONT\"E}, {\sl Wuthering Heights\/} (1847)
\eject
\beginchapter Chapter 9. Equations
The variables in a \MF\ program receive their values by appearing in
{\sl^{equations}}, which express relationships that the programmer
wants to achieve. We've seen in the previous chapter that algebraic
expressions provide a rich 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 \MF\ 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 concepts. In other words, it's important to be able
to {\sl write\/} equations, and it's also important to be able to
{\sl read\/} equations that you or somebody else has written. This
is not nearly as difficult as it might seem at first. The best way
to learn~(1) is to get a lot of practice with~(2) and to generalize
from specific examples. Therefore we shall begin this chapter by
translating a lot of equations into ``simple English.''
\newdimen\longesteq
\setbox0=\hbox{\indent$z_{12}-z_{11}=z_{14}-z_{13}$\quad}
\longesteq=\wd0
\def\\#1\\{\medbreak\noindent
\hbox to\longesteq{\indent#1\hfil}%
\hangindent\longesteq\ignorespaces}
\medskip
\noindent\hbox to\longesteq{\indent\kern-1pt\sl Equation\hfil}%
\kern-1pt{\sl Translation}\smallskip
\\$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 affecting the meaning of that equation in any way.)
\\$"mode"="smoke"$\\
The value of ^"mode" should be equal to the value of ^"smoke". \
(Plain \MF\ 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.)
\\$y_3=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~$z_3$, which is an
abbreviation for the pair of coordinates $(x_3,y_3)$, if you are
using the conventions of plain \MF\!.)
\\$x_9=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.
\\$x_{1l}="curve\_sidebar"$\\
The $x$ coordinate of point $1l$ should be equal to the value of the
variable called "curve\_sidebar". This puts $z_{1l}$ a certain
distance from the left edge~of the type.
\\$x_1=x_2$\\
Points 1 and 2 should have the same $x$ coordinate; i.e., they should
have the same horizontal position, so that one will lie directly
above or below the other.
\\$y_4=y_5+1$\\
Point 4 should be one pixel higher than point~5.
\ (However, points 4 and~5 might be far apart; this equation
says nothing about the relation between $x_4$ and~$x_5$.)
\\$y_6=y_7+2"mm"$\\
Point 6 should be two millimeters higher than point~7. \ (Plain \MF's
^@mode\_setup@ routine sets variable ^"mm" to the number of pixels in a
millimeter, based on the resolution determined by "mode" and "mag".)
\\$x_4=w-.01"in"$\\
Point 4 should be one-hundredth of an inch inside the right edge of
the type. \ (Plain \MF's ^@beginchar@ routine sets variable~^"w" equal
to the width of whatever character is currently being drawn, expressed in
pixels.)
\\$y_4=.5h$\\
Point 4 should be halfway between the baseline and the top of the type.
\ (Plain \MF's @beginchar@ sets ^"h" to the height of the
current character, in pixels.)
\\$y_6=-d$\\
Point 6 should be below the baseline, at the bottom edge of the type.
\ (Each character has a ``^{bounding box}'' that runs from $(0,h)$
at the upper left and $(w,h)$ at the upper right to $(0,-d)$ and~$(w,-d)$
at the lower left and lower right; variable~^"d" represents the depth of
the type. The values 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.)
\\$y_8=.5[h,-d]$\\
Point 8 should be halfway between the top and bottom edges of the type.
\\$w-x_5={2\over3}x_6$\\
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-x_5$ is the ^{distance} from
point~5 to the right edge.)
\\$z_0=(0,0)$\\
Point 0 should be at the ^{reference point} of the current character,
i.e., it should be on the baseline at the left edge of the type.
This equation is an abbreviation for two equations, `$x_0=0$' and `$y_0=0$',
because an equation between pairs of coordinates implies that the $x$
and~$y$ coordinates must both agree. \ (Incidentally, plain \MF\
defines a variable called ^"origin" whose value is $(0,0)$; hence
this equation could also have been written `$z_0="origin"$'.)
\\$z_9=(w,h)$\\
Point 9 should be at the upper right corner of the current character's
bounding box.
\\$"top"\,z_8=(.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,
$x_8$~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"'.)
\\$z_4={3\over7}[z_5,z_6]$\\
Point 4 should be three-sevenths of the way from point~5 to point~6.
\\$z_{12}-z_{11}=z_{14}-z_{13}$\\
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.
\\\smash{\vtop{\hbox{$z_3-z_2=$}
\hbox{\quad$(z_4\!-\!z_2)$\thinspace rotated\thinspace 15}}}\\
Points 3 and 4 should be at the same distance from point~2, but
the direction to point~3 should be 15~degrees counterclockwise from
the direction to point~4.
\exercise Translate the following equations into ``simple English'':
\ (a)~$x_7-9=x_1$; \ (b)~$z_7=(x_4,.5[y_4,y_5])$; \
(c)~$"lft"\,z_{21}="rt"\,z_{20}+1$.
\answer (a)~Point 1 should lie nine pixels to the left of point~7,
considering horizontal positions only; no information is given about the
vertical positions $y_1$ or $y_7$. \ (b)~Point~7 should sit directly
above or below point~4, and its distance up from the baseline should be
halfway between that of points 4 and~5. \ (c)~The left edge of the
currently-picked-up pen, when that pen is centered at point~21, should be
one pixel to the right of its right edge when at point~20. \ (Thus there
should be one clear pixel of white space between the images of the
pen at points 20 and~21.)
\exercise 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.
\answer (a) $y_{13}=-y_{11}$ (or $-y_{13}=y_{11}$, or $y_{13}+y_{11}=0$).
\ (b)~$z_{10}=z_{12}+("mm",-1)$. \ (c)~$z_{43}={1\over3}[(0,h),(w,-d)]$.
Let's return now to the six example points $(z_1,z_2,z_3,z_4,z_5,z_6)$
that were used so often in Chapters 2 and~3. Changing the notation
slightly, we might say that the points are
\begindisplay
$(x_1,y_1)=(0,h)$;&$(x_2,y_2)=(.5w,h)$;&$(x_3,y_3)=(w,h)$;\cr
$(x_4,y_4)=(0,0)$;&$(x_5,y_5)=(.5w,0)$;&$(x_6,y_6)=(w,0)$.\cr
\enddisplay
There are many ways to specify these points by writing a series of
equations. For example, the six equations just given would do fine;
or the short names $z_1$ through~$z_6$ could be used instead of the
long names $(x_1,y_1)$ through~$(x_6,y_6)$. 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 define the
$x$ and~$y$ coordinates separately:
\begindisplay
$x_1=x_4=0;\qquad x_2=x_5=.5w;\qquad x_3=x_6=w;$\cr
$y_1=y_2=y_3=h;\qquad y_4=y_5=y_6=0$.\cr
\enddisplay
\MF\ allows you to state several equations at once, by using more than
^^{=} one equality sign; for example, `$y_1=y_2=y_3=h$' stands for three
equations, `$y_1=y_2$', `$y_2=y_3$', and `$y_3=h$'.
In order to define the coordinates of six points, it's necessary to
write twelve equations, because each equation contributes to the
definition 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 first 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:
\begindisplay
$z_1-z_4=z_2-z_5=z_3-z_6$\cr
$z_2-z_1=z_3-z_2=z_5-z_4=z_6-z_5$\cr
$z_4="origin"$; \ $z_3=(w,h)$.\cr
\enddisplay
^^"origin" First we say that the vectors from $z_4$ to~$z_1$,
from $z_5$ to~$z_2$, and from $z_6$ to~$z_3$, are equal to each other;
then we say the same thing for the vectors from $z_1$ to~$z_2$,
$z_2$ to~$z_3$, $z_4$ to~$z_5$, and $z_5$ to~$z_6$. Finally the
corner points $z_4$ and $z_3$ are given explicitly. That's a total
of seven equations between pairs of coordinates, so it should be
more than enough to define the six points of interest.
However, it turns out that those seven equations are not enough!
For example, the six points
\begindisplay
$z_1=z_4=(0,0)$; \ $z_2=z_5=(.5w,.5h)$; \ $z_3=z_6=(w,h)$
\enddisplay
also satisfy the same equations. A closer look explains why:
The two formulas
\begindisplay
$z_1-z_4=z_2-z_5$\qquad and\qquad $z_2-z_1=z_5-z_4$
\enddisplay
actually say exactly the same thing. \ (Add $z_5-z_1$ to both sides
of the first equation and you get `$z_5-z_4=z_2-z_1$'.) \ Similarly,
$z_2-z_5=z_3-z_6$ is the same as $z_3-z_2=z_6-z_5$. Two of the
seven equations give no new information, so we really have specified
only five equations; that isn't enough. An additional relation
such as `$z_1=(0,h)$' is needed to make the solution unique.
\dangerexercise (For mathematicians.) \ Find a solution to the seven
equations such that $z_1=z_2$. Also find another solution in which
$z_1=z_6$.
\answer (a) $z_1=z_2=z_3=(w,h)$; $z_4=z_5=z_6=(0,0)$.
\ (b)~$z_1=z_6=(.5w,.5h)$; $z_2=(.75w,.75h)$; $z_3=(w,h)$;
$z_4=(0,0)$; $z_5=(.25w,.25h)$.
At the beginning of a \MF\ program, variables have no values,
except that plain \MF\ 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 define 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
\begindisplay
$g_0=g_1=g_2=g_3=g_4=g_5=g_6=g_7=g_8=g_9$
\enddisplay
don't tell us any of the $g$ values. However, the further equation
\begindisplay
$g_0+g_1=1$
\enddisplay
will cause \MF\ to deduce that all ten of the $g$'s are equal to $1\over2$.
\MF\ 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
\begindisplay
$a+b+2c=3$;\cr
$a-b-2c=1$\cr
\enddisplay
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 \MF\ can compute a
variety of things with unknown variables; but sometimes a quantity
must be known before it can be used. For example, \MF\ 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 first in order to make critical
values known in the others. For example, \MF\ will find the
solution $(a,b,c)=(2,7,-3)$ to 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\ast(b+c)=8$', you would not have
been able to give the last one first, because \MF\ would have refused
to multiply the unknown quantity~$a$ by another unknown quantity $b+c$.
Here are the main things that \MF\ can do with unknown quantities:
\begindisplay
$-\$\cr
$\+\$\cr
$\-\$\cr
$\\ast\$\cr
$\\ast\$\cr
$\/\$\cr
$\[\,\]$\cr
$\[\,\]$\cr
\enddisplay
Some of the operations of plain \MF\!, defined in Appendix~B\null, also work
with unknown quantities. For example, it's possible to say
^"top"\thinspace\, ^"bot"\thinspace\,
^"lft"\thinspace\, ^"rt"\thinspace\, and even
\begindisplay
@penpos@\(\,\thinspace\).
\enddisplay
\danger A \MF\ program can say `\$[a,b\mkern1mu]$' when $a-b$ is
known, and variable~$a$ can be compared to variable~$b$ in boolean
expressions ^^{comparison} like `$a**0$, \MF\ chooses an
independent variable~$v_k$ for which $c_k$ is maximum, and rewrites
the equation in the form
\begindisplay
{\tt\#\#} $v_k=(\alpha-c_1v_1-\cdots-c_{k-1}v_{k-1}-c_{k+1}v_{k+1}-
\cdots-c_mv_m)/c_k$.
\enddisplay
Variable $v_k$ becomes dependent (if $m>1$) or known (if $m=1$).
\danger Inconsistent equations are equations that have no solutions.
For example, if you say `$0=1$', \MF\ will issue an error message
^^{off by x}
saying that the equation is ``off 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 off 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.
\danger 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$. \MF\ 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
`$z_3=(0,h)$' will not trigger an error message when the program
has previously established that $x_3=0$ or that $y_3=h$ or both.
\danger Sometimes you might have to work a little bit to put an equation
into a form that \MF\ can handle. For example, you can't say
\begindisplay
$x/y=2$
\enddisplay
when $y$ is independent or dependent, because \MF\ allows ^{division}
only by known quantities. The alternative
\begindisplay
$x=2y$
\enddisplay
says the same thing and causes the computer no difficulties;
furthermore it is a correct equation even when $y=0$.
\ddanger \MF's ability to remember previous equations is limited to
``linear'' dependencies ^^{linear dependencies} as explained above.
A mathematician might want to introduce the condition $x\ge0$ by giving an
equation such as `$x=\mathop{\rm abs}x$'; but \MF\ is incapable
of dealing with such a constraint. Similarly, \MF\ can't cope with
an equation like `$x=\mathop{\rm floor}x$', which states that
$x$~is an integer. Systems of equations that involve the ^{absolute
value} and/or ^{floor} operation can be extremely difficult to solve,
and \MF\ doesn't pretend to be a mathematical genius.
\ddanger The rules given earlier explain how an independent variable
can become dependent 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,
\begintt
## c=-0.5b-0.5a+1.5
## d=0.5b-0.25a+1.5
\endtt
Now suppose that the next statement is `|numeric|~|a|', meaning that the
old value of variable~$a$ should be discarded. \MF\ 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
\begintt
### 0.5a=-0.5b-c+1.5
\endtt
^^{hash hash hash} meaning that $0.5a$ will be replaced by $-c-{1\over2}b
+{3\over2}$ in all dependencies, before $a$ is 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 coefficient of dependency with respect
to the variable that will disappear.
\danger A designer often wants to stipulate that a certain point lies on
a certain line. ^^{line, point to be on} This can be done easily by
using a special feature of plain \MF\ called `^"whatever"', which
stands for an anonymous numeric variable that has a different unknown
value each time you use it. For example,
\begindisplay
$z_1="whatever"[z_2,z_3]$
\enddisplay
states that point 1 appears somewhere on the straight line that passes
through points 2 and~3. \ (The expression $t[z_2,z_3]$ represents that
entire straight line, as $t$ runs through all values from $-\infty$ to
$+\infty$. We want $z_1$ to be equal to $t[z_2,z_3]$ for some value of~$t$,
but we don't care what value it is.) \ The expression `"whatever"$[z_2,z_3]$'
is legal whenever the difference $z_2-z_3$ is known; it's usually used
only when $z_2$ and $z_3$ are both known, i.e., when both points have been
determined by prior equations.
\danger 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 off more of the
computer's amazing ability to deduce explicit values from implicit
statements.
\ninepoint % it's all dangerous from here on!
\setbox0=\hbox{\indent$z_7-z_6="whatever"\ast(z_3-z_2)$\quad}
\longesteq=\wd0
\noindent\hbox to\longesteq{\indent\kern-1pt\sl Equation\hfil}%
\kern-1pt{\sl Translation}\smallskip
\\$z_5-z_4="whatever"\ast\mathop{\rm dir}30$\\
The angle between points 4 and~5 will be $30^\circ$ above the horizon.
\ (This equation can also be written `$z_4=z_5+"whatever"\ast\mathop{\rm
dir}30$', which states that point~4 is obtained by starting at point~5
and moving by some unspecified multiple of ^{dir}$\,30$.)
\\$z_7-z_6="whatever"\ast(z_3-z_2)$\\
The line from point~6 to point~7 should be ^{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 unspecified, so it will be determined by other equations.
\dangerexercise If $z_1$, $z_2$, $z_3$, and $z_4$ are known points,
how can you tell \MF\ to compute the point $z$ that lies on the
^{intersection} of the lines $z_1\to z_2$ and $z_3\to z_4$?
\answer $z="whatever"[z_1,z_2]$; $z="whatever"[z_3,z_4]$. \ (Incidentally,
it's interesting to watch this computation in action. Run \MF\ with
|\tracingequations:=|\allowbreak|tracingonline:=1| and say, for example,
\begintt
z=whatever[(1,5),(8,19)]; z=whatever[(0,17),(6,1)];
\endtt
the solution appears as if by magic.
If you use |alpha| and |beta| in place of the whatevers, the machine will
also calculate values for "alpha" and "beta".)
\dangerexercise Given five points $z_1$, $z_2$, $z_3$, $z_4$, and $z_5$,
explain how to compute $z$ on the line $z_1\to z_2$ such that the line
$z\to z_3$ is parallel to the line $z_4\to z_5$.
\answer $z="whatever"[z_1,z_2]$; $z-z_3="whatever"\ast(z_5-z_4)$.
\dangerexercise What \MF\ equation says that the line between points
11 and~12 is {\sl^{perpendicular}\/} to the line between points 13 and~14?
\answer $z_{11}-z_{12}="whatever"\ast(z_{13}-z_{14})$ ^{rotated} 90,
assuming that $z_{13}-z_{14}$ is known. \ (It's also possible to say
`$(z_{11}-z_{12})\mathbin{\rm dotprod} (z_{13}-z_{14})=0$', ^^{dotprod}
although this risks overflow if the coordinates are large.)
\dangerexercise (For mathematicians.) \ Given three points $z_1$, $z_2$,
and $z_3$, explain how to compute the distance from $z_1$ to the straight
line through $z_2$ and $z_3$.
\answer One solution constructs the point $z_4$ on $z_2\to z_3$ such
that $z_4\to z_1$ is perpendicular to $z_2\to z_3$, using ideas like
those in the previous two exercises: `$z_4="whatever"[z_2,z_3]$;
$z_4-z_1="whatever"\ast(z_3-z_2)$ rotated 90'. Then the requested distance
^^{abs} ^^{ypart}^^{angle}
is ${\rm length}(z_4-z_1)$. But there's a slicker solution: Just calculate
$$\hbox{abs ypart$((z_1-z_2)\mathbin{\rm rotated}-{\rm angle}(z_3-z_2))$.}$$
\ddangerexercise (For mathematicians.) \ Given three points $z_1$,
$z_2$, $z_3$, and a length~$l$, explain how to compute the two points
on the line $z_2\to z_3$ that are at distance~$l$ from $z_1$. \ (Assume
that $l$~is greater than the distance from $z_1$ to the line.)
\answer It would be nice to say simply `$z="whatever"[z_2,z_3]$' and
then to be able to say either `length$(z-z_1)=l$' or `$z-z_1=(l,0)$
rotated "whatever"'; but neither of the second equations is legal. \
(Indeed, there couldn't possibly be a legal solution that has this general
flavor, because any such solution would determine a unique $z$, while
there are two points to be determined.) \ The best way seems to be to
compute $z_4$ as in the previous exercise, ^^{pythagorean subtraction} and
then to let
$v=(l\mathbin{+{-}+}\mathop{\rm length} (z_4-z_1))\ast\mathop{\rm
unitvector}(z_3-z_2)$; ^^{unitvector} ^^{length}
the desired points are then $z_4+v$ and $z_4-v$.
\ddangerexercise The applications of "whatever" that we have seen so far
have been in equations between {\sl pairs\/} of numeric values, not
in equations between simple numerics. Explain why an equation like
`$a+2b="whatever"$' would be useless.
\answer Such an equation tells us nothing new about $a$ or $b$. Indeed,
each use of "whatever" introduces a new independent variable, and
each new independent variable ``uses up'' one equation, since we need
$n$ equations to determine the values of $n$~unknowns. On the other hand
an equation between pairs counts as two equations; so there's a net
gain of one, when "whatever" appears in an equation between pairs.
\danger All of the equations so far in this chapter have been between numeric
expressions or pair expressions. But \MF\ actually allows equations
between any of the eight types of quantities. For example, you can write
\begintt
s1="go"; s1&s1=s2
\endtt
if $s_1$ and $s_2$ are string variables; this makes $s_1=\null$|"go"|
and $s_2=\null$|"gogo"|. Moreover, the subsequent equations
\begintt
s3=s4; s5=s6; s3=s5; s4=s1&"sh"
\endtt
will make it possible for the machine to deduce that $s_6=\null$|"gosh"|.
\danger But nonnumeric equations are not as versatile as numeric
ones, because \MF\ does not perform operations on unknown quantities
^^{unknown quantities, nonnumeric}
of other types. For example, the equation
\begintt
"h"&s7="heck"
\endtt
cannot be used to define $s_7=\null$|"eck"|, because the ^{concatenation}
operator~|&| works only with strings that are already known.
\ddanger 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.
\endchapter
Let ``X'' equal my father's signature.
\author FRED ^{ALLEN}, {\sl Vogues\/} (1924) % NYT review of show, Mar 28'24
% quoted in Much Ado About Me, p288
\bigskip
ALL ANIMALS ARE EQUAL
BUT SOME ANIMALS ARE MORE EQUAL THAN OTHERS
\author GEORGE ^{ORWELL}, {\sl Animal Farm\/} (1945) % Chapter 10
\eject
\beginchapter Chapter 10. Assignments
Variables usually get values by appearing in equations, as described in
the preceding chapter. But there's also another way, in which `^|:=|'
is used instead of~`|=|'. For example, the |io.mf| program in Chapter~5
said
\begintt
stem# := trial_stem * pt#
\endtt
when it wanted to define 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 {\sl^{assignment}\/}
operation. It was convenient for |io.mf| to define |stem#| with an
assignment instead of an equation, because |stem#| was getting several
different values within a single font. The alternative would have been to say
\begintt
numeric stem#; stem# = trial_stem * pt#
\endtt
(thereby specifically undefining 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,
\begintt
code := code + 1
\endtt
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.
\dangerexercise Is it possible to achieve the effect of `$"code":="code"+1$'
by using equations and @numeric@ declarations but not assignments?
\answer Yes, but it must be done in two steps: `@numeric@ "newcode";
$"newcode"="code"+1$; @numeric@ "code"; $"code"="newcode"$'.
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
significantly, 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 statement 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 significant, because
assignments play a relatively minor r\^ole in \MF\ programs. The best
programming strategy is usually to specify equations instead of
assignments, because equations indicate the relationships between
variables in a declarative ^^{declarative versus imperative} ^^{imperative
versus 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; \MF's equation
mechanism liberates us from that more complicated style of programming,
because it lets the computer take over the job of solving equations.
The use of assignments often imposes a definite order on the statements of
a program, because the value of a variable is different before and after
an assignment takes place. Equations are simpler than assignments because
they can usually be written down in any order that comes naturally to you.
Assignments do have their uses; otherwise \MF\ wouldn't bother with
`|:=|' at all. But experienced \MF\ programmers introduce assignments
sparingly---only when there's a good reason for doing so---because
equations are generally easier to write and more enlightening to read.
\danger \MF's ^{internal quantities} like "tracingequations" always have
known numeric values, so there's no way to change them except by giving
assignments. The computer experiment in Chapter~9 began with
\begintt
\tracingequations:=tracingonline:=1;
\endtt
this illustrates the fact that multiple assignments are possible, just
like multiple equations. Here is the complete syntax for equations
and assignments:
\beginsyntax
**\is[=]
\is[:=]
\is\alt\alt
\endsyntax
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$'.
\ddanger 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.
\dangerexercise Suppose that you want variable $x_3$ to become ``like new,''
^^{variables, reinitializing} ^^{reinitializing} ^^{independent variables}
completely independent of any value that it formerly had; but you don't
want to destroy the values of~$x_1$ and~$x_2$. You can't say `^@numeric@
$x[\,]$', because that would obliterate all the $x_k$'s. What can you do
instead? \checkequals\xwhat\exno
\answer The assignment `$x_3:=\null$^"whatever"' does exactly what you want.
\ddangerexercise Apply \MF\ to the short program
\begindisplay
@string@ $s[\,]$; \ $s_1=s_2=s_3=s_4$; \ $s_5=s_6$; \ $s_2:=s_5$; \
@showvariable@ $s$;
\enddisplay
and explain the results you get.
\answer The result shows that $s_1=s_3=s_4$ and $s_2=s_5=s_6$ now:
\begintt
s[]=unknown string
s1=unknown string s3
s2=unknown string s6
s3=unknown string s4
s4=unknown string s1
s5=unknown string s2
s6=unknown string s5
\endtt
(The assignment $s_2:=s_5$ broke $s_2$'s former relationship with $s_1$,
$s_3$, and $s_4$.)
\ddanger If other variables depend on $v$ when $v$ is assigned a new value,
the other variables do not change to reflect 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 \MF\ 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.)
\ddangerexercise Apply \MF\ to the program
\begindisplay
$"tracingequations":="tracingonline":=1$;\cr
$a=1$; \ $a:=a+b$; \ $a:=a+b$; \ $a:=a+b$;\cr
@show@ $a,b$;\cr
\enddisplay
and explain the results you get.
\answer The results are
\begindisplay
|## a=1|\cr
|## a=b+1|&(after the first assignment)\cr
|## b=0.5a-0.5|&(after the second assignment)\cr
|### -1.5a=-%CAPSULEnnnn-0.5|&(after the third assignment)\cr
|## a=%CAPSULEnnnn|&(after the third, see below)\cr
|>> a|&(after `@show@'; variable $a$ is independent)\cr
|>> 0.33333a-0.33333|&(this is the final value of $b$)\cr
\enddisplay
^^|CAPSULE| Let $a_k$ denote the value of $a$ after $k$ assignments were made.
Thus, $a_0=1$, and $a_1$ was dependent on the independent variable~$b$.
Then $a_1$ was discarded and $b$ became dependent on the independent
variable~$a_2$. The right-hand side of the third assignment was
therefore $a_2+b$. At the time $a_2$ was about to be discarded, \MF\
had two dependencies $b=0.5a_2-0.5$ and $\kappa=1.5a_2-0.5$, where
$\kappa$ was a nameless ``^{capsule}'' inside of the computer, representing
the new value to be assigned. Since $\kappa$ had a higher coefficient
of dependency than~$b$, \MF\ chose to make $\kappa$ an independent variable,
after which $-1.5a_2$ was replaced by $-\kappa-0.5$ in all dependencies; hence
$b$ was equal to $0.33333\kappa-0.33333$. After the third
assignment was finished, $\kappa$ disappeared and $a_3$ became independent
in its place. \ (The line `|##| |a=%CAPSULEnnnn|' means that $a$~was
temporarily dependent on $\kappa$, before $\kappa$ was discarded. If
the equation $a=\kappa$ had happened to make $\kappa$ dependent on~$a$, rather
than vice versa, no ^^{hash hash} `|##|' line would have been printed;
such lines are omitted when a capsule or part of a capsule has been made
dependent, unless you have made ^"tracingcapsules"$\null>0$.)
\endchapter
At first his assignment had pleased,
but as hour after hour passed
with growing weariness,
he chafed more and more.
\author C. E. ^{MULFORD}, {\sl Hopalong Cassidy\/} (1910) % Chap 17 p154
\bigskip
\