summaryrefslogtreecommitdiff
path: root/info/challenges/aro-bend/answer.016
blob: f1e04970b72d165e1ef0ec044061253c2b62c019 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
[There was an error in the first posted version: \twelverm instead of
the first \tenrm in the statement

  \font\tenrm = \fontname\tenrm scaled 1200

The posting containing this correction is appended below.]

Date: 27 Jan 1994 11:59:48 -0500 (EST)
From: Michael Downes <MJD@MATH.AMS.ORG>
Subject: Around the Bend #16, answers
To: info-tex@shsu.edu
X-ListName: TeX-Related Network Discussion List <INFO-TeX@SHSU.edu>

Here is my commentary on Around the Bend #16.

% \mag=1728 \hfuzz=1pt \tabskip=1pt \baselineskip=12pt
% \topskip=10pt \lineskiplimit=1pt \lineskip=1pt

% \mag=\time \ifnum\mag>1500 \T\else\F\fi                         %  (1) 

(1): F --- At the time of the \ifnum, \mag is in the range [0,1440)
depending on what time it was when you ran TeX.

% \mag=\number\year \ifnum\mag>1500 \T\else\F\fi                  %  (2) 

(2): F --- At the time of the \ifnum, \mag still has its previous value
because TeX is still scanning for digits to add on after "1994".

% \hfuzz=99pt \ifdim\hfuzz=99pt \T\else \F\fi                     %  (3) 

(3): T --- Everything fine, dimension scanning terminated with the
space after "99pt".

% \tabskip=\z@ \ifdim\tabskip<\p@\T\else\F\fi                     %  (4) 

(4): F --- \z@ is a dimension register, therefore it serves only as the
first part of the glue value that TeX is looking for. At the time of the
\ifdim, TeX is still looking for `plus' or `minus' and hasn't yet
finished the assignment of \tabskip.

% \tabskip=\p@ minus2pt \ifdim\tabskip>\z@\T\else\F\fi            %  (5) 

(5): T --- Glue value scanning terminated properly. \p@ is a dimension
register like \z@ but the additional clause `minus 2pt' fills out the
glue value to the required three parts.  TeX assumes `plus 0pt' when it
finds a `minus' clause without a preceding `plus' clause. Note that TeX
does *not* continue scanning for a possible `plus' after reading a minus
component. Unlike the height, depth, and width components of a \vrule or
\hrule, the components of a glue value have a required order and each
part can only occur once.

% \baselineskip=-\prevdepth \ifdim\baselineskip=12pt \T\else\F\fi %  (6) 

(6): T --- At the beginning of a vbox or at the beginning of a TeX run
\prevdepth = -1000pt. So it would seem that \baselineskip should get set
to +1000pt and the test should be False; but \prevdepth is a dimension
register, not a glue register, so following stretch or shrink components
are still possible, and \baselineskip does not yet have its new value at
the time of the test.

% \advance\baselineskip 2\topskip                                 %  (7) 
%   \ifdim\baselineskip>\@m\p@ \T\else\F\fi                       %        

(7): F --- Without the factor 2 in front of \topskip, the test would
be True: \topskip is a glue register so TeX would copy each component of
\topskip to the corresponding component of \baselineskip; then, having plus
and minus components already in hand, TeX would not scan ahead for
`plus' or `minus'. However, a preceding factor for a glue register
causes TeX to use only the first component of the glue register,
multiplied by the given factor, which means that additional scanning is
then attempted for possible stretch or shrink components.

% \lineskiplimit=\z@ \ifnum\lineskiplimit>0 \T\else\F\fi          %  (8) 

(8): F --- Normal termination of dimension scanning. \lineskiplimit
is a dimen register, not a glue register, so the dimen constant \z@ is
sufficient to complete the assignment and TeX scans no further.

% \lineskip=\z@skip \ifdim\lineskip>\lineskiplimit \T\else\F\fi   %  (9) 

(9): F --- Normal termination of glue scanning. \z@skip is a glue
register so it suffices to complete the assignment of \lineskip. Compare
to the \tabskip assignments above.

% \kern2pc\ifdim\lastkern=2pc \T \else\F\fi                       % (10)

(10): F --- At the time of the \ifdim, TeX is still looking for
an optional final space at the end of the dimension value "2pc". If it
were 2\p@ instead of 2pc, the test would evaluate to True.

% \hskip1em
%   \ifvmode\T\else\ifdim\lastskip>\z@\msg{FT}\else\msg{FF}\fi\fi % (11) 

(11) FF --- TeX enters horizontal mode as soon as the \hskip command
comes along, before it finishes scanning the skip amount. So the
\ifvmode test is false. The \ifdim test is also false because scanning
is not yet complete (TeX is looking ahead for a plus or minus component)
so the glue has not yet been entered into the horizontal list, so it is
not accessible to \lastskip.

For more on the switch into horizontal mode, see `TeX from \indent to
\par', Marek Ry{\'c}ko and Bogus{\l}aw Jackowski, TUGboat 14/3, October
1993 (1993 Annual Meeting Proceedings), pp. 171--176.

% \font\cmrtest=cmr10 \ifx\cmrtest\tenrm \T\else\F\fi             % (12)

(12) F --- Interestingly, the following versions of the \ifx test are
also false at that point: \ifx\cmrtest\undefined, \ifx\cmrtest\relax.
The reason is that after "\font\cmrtest" TeX immediately sets \cmrtest =
\nullfont, before scanning the rest of the font assignment. So the test
\ifx\cmrtest\nullfont would yield True. According to the TeXbook, the
reason for this behavior is to allow statements of the form

  \font\cmrtest=cmr10 \cmrtest

for switching to the font \cmrtest immediately after it is defined. TeX
does a bit of boomeranging in such a case:

  \font\cmrtest          % set \cmrtest = \nullfont
  =cmr10                 % space terminates font name, start looking for
                         % "at" or "scaled"
  \cmrtest               % \cmrtest = \nullfont = nonexpandable, not
                         % "a", not "s"; terminate the font assignment
                         % and put back the \cmrtest token to be read
                         % again:
  \cmrtest               % Now \cmrtest selects the given font

Although I sympathize with Knuth's desire to smooth out a potential
problem for naive users, I wonder if it only encourages users to pay
less attention to the nitty-gritty details of scanning and expansion,
and therefore lay themselves open to greater confusion later on when
something similar fails (inconsistently!) to work. I'd have thought it
better to require, and document, proper termination of font assignment
scanning by \relax or whatever. Users would have to be a little more
knowledgeable but they would be rewarded with a more consistent language
to work with.  As it stands TeX unnaturally forbids certain
constructions that are perfectly colloquial to anyone who has an ear for
the TeX language, such as

  \font\tenrm = \fontname\tenrm\space scaled 1200

I hold a similar opinion for the way \chardef and \mathchardef set their
arguments to \relax before scanning the number on the right-hand-side of
the assignment. Occasionally I would *like* to be able to write
something like \chardef\foo=\ifcase\foo 1\or 2\else 3\fi, but TeX
doesn't allow that.

One could argue that the \chardef behavior should for consistency be
imitated by \edef, \xdef so that if \foo is undefined then

  \edef\foo{a\foo}

should not give an undefined control-sequence error for the \foo in the
replacement text, but make it temporarily equivalent to \relax and leave
it there.  (Of course, this means that executing \foo will then start up
an infinite loop, but my point was that it's the behavior of \chardef
that should be changed to achieve consistency, not the behavior of
\edef.)

========================================================================

At the end of Exercise #16 there was the question `Where should \relax
should be inserted?'

\relax should be inserted just before the \if... in statements (2), (6),
(7), (11), and (12). In statement (4) \z@skip should be used instead of
\z@; then \relax is unnecessary. A space suffices instead of \relax in
(10). I would also tend to put a \relax at the end of the preliminary
assignments to \baselineskip and \lineskip, as a matter of principle; I
like to make sure that scanning is definitely terminated at the end of a
line, so that if any error occurs during the scanning, TeX will show the
line containing the assignment statement and not a later line. This is
particularly relevant for font assignments: If foo10.tfm does not exist
on your system, then the assignment

  \font\foo=foo10
  <blank line>

will cause TeX to show you the blank line instead of the preceding line
in the error context:

  ! Font \foo=foo10 not loadable: Metric (TFM) file not found.
  <to be read again>
                     \par
  l.2

And if the following material is some complicated macro instead of a
blank line, TeX will go into the replacement text of the macro, looking
for "at" or "scaled", before giving the error message!

Michael Downes %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mjd@math.ams.org (Internet) ASCII 32--54,55--126: !"#$%&'()*+,-./0123456
789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Date: 28 Jan 1994 08:01:12 -0500 (EST)
From: Michael Downes <MJD@MATH.AMS.ORG>
Subject: Around the Bend #16, answers, correction
To: info-tex@shsu.edu

Instead of

  \font\twelverm = \fontname\tenrm\space scaled 1200

read

  \font\tenrm = \fontname\tenrm\space scaled 1200

The latter line is what I originally wrote but I changed it in an obtuse
moment a day later, forgetting the very point it was supposed to
illustrate.