[comp.text.tex] \the \baselineskip

xiaofei@ACSU.BUFFALO.EDU (02/17/91)

If I say
``
\the\baselineskip
\baselineskip=2.0\baselineskip
\the\baselineskip
''
 
I expect the first \the\baselineskip gives me a ``12.0pt'' and the
second one goves me a ``24.0pt''. But it is not the case, they both
give me ``12.0pt'' which I find it difficult to understand.
 
In order to get the results I expected I have to put \par in the
first sentence. But this does not make sense to me. The value for
\baselineskip HAS BEEN CHANGED regardless if there is a baselineskip.
 
I expect the basic logic to work:
``
x=1
means x is one
x=2\times x
then x is two obviously
''
 
What is wrong with the way I am thinking?

X066TR@TAMVM1.BITNET ("Thomas J. Reid") (02/17/91)

On Sun, 17 Feb 91 03:05:17 EST xiaofei@acsu.buffalo.edu said:
>If I say
>``
>\the\baselineskip
>\baselineskip=2.0\baselineskip
>\the\baselineskip
>''
>
>I expect the first \the\baselineskip gives me a ``12.0pt'' and the
>second one goves me a ``24.0pt''. But it is not the case, they both
>give me ``12.0pt'' which I find it difficult to understand.
 
The point which you are not understanding is the difference between TeX's
parsing tokens, and executing commands.  TeX processes the sequence by
first expanding "\the\baselineskip" into its current value of "12.0pt".
It then begins parsing the tokens "\baselineskip", "=", "2", ".", "0",
"\baselineskip".  At this point, TeX does not yet realize that it has a
complete command which it can execute, so it continues parsing.  It then
finds "\the" which causes it to immediately expand the "\baselineskip"
which follows it.  This generates a new set of tokens: "1", "2", ".",
"0", "p", and "t" which TeX stacks.  Finally, TeX executes the assignment
command and changes the value of \baselineskip to 24pt.  Thus, it is
the look-ahead action of the token parser which is causing your problem.
 
To work around this problem, it is merely necessary to insert a token
between the assignment and the second expansion of \the\baselineskip
to cause TeX to actually make the assignment.  Your test of inserting
\par at this point would do the trick; however, if you didn't want a
paragraph break there, it would have a bad side-effect.  The best thing
to do is to insert \relax after the assignment.
 
The processing of dimensional arguments is one of the more confused
aspects of TeX but is better understood when one realizes the two phases
of parsing tokens and actually processing the commands.
 
Regards,
 
Tom Reid

eijkhout@s41.csrd.uiuc.edu (Victor Eijkhout) (02/18/91)

xiaofei@ACSU.BUFFALO.EDU writes:

>What is wrong with the way I am thinking?

Dunno, but let's think like TeX:

>\the\baselineskip

No problem. Print 12.0pt

>\baselineskip=2.0\baselineskip

Ha! We're doing a <glue> assignment. Lessee...
The right hand side can be a glue parameter (e.g. \parskip),
no that's not the case, it starts with 2.0.
So maybe it's a glue denotation:
    <dimen> plus <fildimen> minus <fildimen>
            ^ optional      ^ optional
First 2.0/baselineskip. That's a <dimen> all right
(note (this is me, VE, talking) that if \baselineskip=12pt plus 1pt,
then 2.0\baselineskip is just 12pt, because it's a <dimen>;
back to TeX:)
now let's see if there's a `plus' or `minus' spec after this.

>\the\baselineskip

Hm ... `\the' ... I can expand that. Let's see
what comes out. No. This just prints 12.0pt. Does not
look like a `plus' or `minus'. Pity. I'll just assign the
2.0\baselineskip.

So far \TeX.

Now if you'd written once more \the\baselineskip,
you would have gotten 24.0pt. The second one was
just printed too early.

Victor. 

barr@TRIPLES.MATH.MCGILL.CA (Michael Barr) (02/18/91)

Indeed if you run the code:
 
\the\baselineskip
\baselineskip=2.0\baselineskip
\the\baselineskip
\bye
 
through tex, the output is
12.0pt12.0pt
 
If you run the code
 
\the\baselineskip
\baselineskip=2.0\baselineskip{}
\the\baselineskip
\bye
 
through tex, the output is
12.0pt 24.0pt
 
If you run
 
\the\baselineskip
\baselineskip=2.0\baselineskip\relax
\the\baselineskip
\bye
 
the output
12.0pt24.0pt
 
What is going on here is one of the most pernicious gotcha's in tex.
The fact is that when tex reads a numerical quantity (and dimensions are
also stored as numbers, in terms of sp's), tex has to read far enough to
ascertain that the number has actually finished.  If it discovers that
the number actually finished a while back, it does not go back and
reread what has already been read.  In the first case, it read the
\baselineskip=2.0\baselineskip and then continued past the carriage
return (which was swallowed by the control sequence) to read the second
\the, which apparently caused it to read the \baselineskip and then
executed the code that it had absorbed.  At that point, the value of
\baselineskip was indeed 24.0pt, but what printed was the value when it
was read.  For some reason, it doesn't do this if instead of \the you
execute \showthe\baselineskip.  I don't understand why the two behave
differently; I can only assume one takes place in the stomach and the
other in the esophagous, or something like that.  TeX's digestive tract
is something of a black hole, at least to me.
 
The remaining two contain a pair of braces or a \relax, both of which
signal TeX that the dimension it is examining has ended and so it
doesn't continue to read on.  LaTeX has \relax inserted at various dates
in strategic places, almost surely to forestall unexpected occurrences
like this when a macro appears in a place not anticipated at the time it
was originally coded.  If you insert the pair of braces, the carriage
return isn't swallowed and you get a space in there; with relax, you
don't get the space.
 
Michael Barr

X066TR@TAMVM1.BITNET ("Thomas J. Reid") (02/18/91)

On Sun, 17 Feb 91 16:48:31 EST Michael Barr said:
>      ...  For some reason, it doesn't do this if instead of \the you
>execute \showthe\baselineskip.  I don't understand why the two behave
>differently; I can only assume one takes place in the stomach and the
>other in the esophagous, or something like that.  TeX's digestive tract
>is something of a black hole, at least to me.
 
Michael,
 
You must have tried the same thing I did when I saw the first note: run
TeX substituting \showthe for \the.  I noticed the same thing you did, but
did not think anything of it at the time.  After getting your note, I
studied the problem again.
 
It turns out that \the and \showthe are getting processed in different
parts of TeX's "digestive tract"; \the in its "mouth," and \showthe in its
"stomach."  This explains why the two are different.
 
The original poster asked me off-list for a pointers on understanding
when and where expansions take place.  The best place that I've found in
_The_TeXbook_ is on page 373:
 
   "TeX's control sequences are divided into two main categories,
    'expandable' and 'unexpandable'; the former category includes
    all macros and \if...\fi tests, as well as special operations
    like \the and \input, while the latter category includes the
    primitive commands listed in Chapter 24.  The expansion of
    expandable tokens takes place in TeX's 'mouth,' but primitive
    commands (including assignments) are done in TeX's 'stomach.'"
 
The \showthe primitive is among those listed in Chapter 24 (on page 279).
 
---Tom Reid

MJD@MATH.AMS.COM (Michael Downes) (02/18/91)

I don't think anyone has yet pointed out explicitly that in the
combination
 
  \the\baselineskip
  \baselineskip=2.0\baselineskip
  \the\baselineskip
 
TeX is looking ahead after the second line to see if "plus" or "minus"
is coming up next.
 
If you were to say
 
  \toks0={plus 3pt minus 1pt}
 
and add a line saying \the\toks0\relax before the second
\the\baselineskip, then you would find TeX reporting
 
  24.0pt plus 3.0pt minus 1.0pt
 
as the new value of \baselineskip; TeX would expand \the\toks0,
and find some valid additions to the baselineskip assignment currently
in progress, and therefore concatenate them to the assignment.
 
Note that in the assignment statement
 
  \parskip=\baselineskip
 
TeX would not look ahead for a "plus" or "minus" key word.
In a direct skip register to skip register assignment
the stretch and shrink of the right-hand register are taken
as the "plus" and "minus" components and therefore TeX looks
no further.  *However*, any multiplier (such as 2.0) coerces
a skip register to a dimension (see the TeXbook, answer to
exercise 24.3), and then the stretch and shrink of the
right-hand skip register are ignored; that's why TeX looks further.
If you wrote instead
 
  \multiply\baselineskip by 2
 
the coercion would not take place.  However, since \multiply
only works with integers, this wouldn't allow you to specify
baselineskip factors of 1.7 or whatever, except by using
\multiply and \divide statements to get the rational equivalent
of the desired decimal.
 
TeX's rules for calculating with numbers and dimensions are
certainly idiosyncratic, but what seems to be rarely realized is
that Knuth was working under two significant constraints that are
unique to TeX: (1) the programming and the data are symbiotic;
therefore you have to worry about distinguishing arithmetic
fragments that should be executed and ones that should be typeset.
(2) One of Knuth's goals was to make TeX as small and fast as
possible, so that it could be made to work on as many machines as
possible, even less powerful ones.  He could probably have added a
full-fledged arithmetic parser that would handle everything nicely,
but then it might have taken until 1990 instead of 1984 for TeX to
run on XT and AT-class machines, because of the larger program
size.  And/or run slower because of the virtual memory swapping
operations involved.  Knuth only implemented the minimum set of
arithmetic operations that allowed him to do what he wanted.
 
Michael Downes
mjd@math.ams.com (Internet)
-------